require "test_helper" class EarningTest < ActiveSupport::TestCase setup do @user = users(:one) || User.create!(email: "test@example.com", password: "password") @event = events(:concert_event) || Event.create!(name: "Test Event", slug: "test-event", description: "Description", venue_name: "Venue", venue_address: "Address", latitude: 48.8566, longitude: 2.3522, start_time: Time.current, user: @user) @order = orders(:paid_order) || Order.create!(user: @user, event: @event, status: "paid", total_amount_cents: 10000) @earning = Earning.create!(event: @event, user: @user, order: @order, amount_cents: 9000, fee_cents: 1000, status: :pending) end test "valid earning" do assert @earning.valid? end test "amount_cents must be present and non-negative" do @earning.amount_cents = nil assert_not @earning.valid? assert_includes @earning.errors[:amount_cents], "can't be blank" @earning.amount_cents = -1 assert_not @earning.valid? assert_includes @earning.errors[:amount_cents], "must be greater than or equal to 0" end test "fee_cents must be present and non-negative" do @earning.fee_cents = nil assert_not @earning.valid? assert_includes @earning.errors[:fee_cents], "can't be blank" @earning.fee_cents = -1 assert_not @earning.valid? assert_includes @earning.errors[:fee_cents], "must be greater than or equal to 0" end test "status must be present" do @earning.status = nil assert_not @earning.valid? assert_includes @earning.errors[:status], "can't be blank" end test "stripe_payout_id must be unique if present" do @earning.stripe_payout_id = "test_payout" @earning.save! duplicate = @earning.dup duplicate.stripe_payout_id = "test_payout" assert_not duplicate.valid? assert_includes duplicate.errors[:stripe_payout_id], "has already been taken" end test "belongs to associations" do assert_instance_of Event, @earning.event assert_instance_of User, @earning.user assert_instance_of Order, @earning.order end test "status enum" do assert_equal 0, Earning.statuses[:pending] assert_equal 1, Earning.statuses[:paid] assert @earning.pending? assert_not @earning.paid? @earning.status = :paid @earning.save! assert @earning.paid? assert_not @earning.pending? end test "pending scope from enum" do pending_earning = Earning.create!(event: @event, user: @user, order: @order, amount_cents: 9000, fee_cents: 1000, status: :pending) paid_earning = Earning.create!(event: @event, user: @user, order: @order, amount_cents: 4500, fee_cents: 500, status: :paid) assert_includes Earning.pending, pending_earning assert_not_includes Earning.pending, paid_earning end test "paid scope from enum" do pending_earning = Earning.create!(event: @event, user: @user, order: @order, amount_cents: 9000, fee_cents: 1000, status: :pending) paid_earning = Earning.create!(event: @event, user: @user, order: @order, amount_cents: 4500, fee_cents: 500, status: :paid) assert_not_includes Earning.paid, pending_earning assert_includes Earning.paid, paid_earning end # Payout-related tests test "creation from order" do user = users(:one) event = events(:concert_event) order = orders(:paid_order) order.update!(status: "paid", total_amount_cents: 10000) # Assume Earning.create_from_order(order) or callback creates earning Earning.create_from_order(order) earning = Earning.where(order: order).first assert_not_nil earning assert_equal 9000, earning.amount_cents # After fees: assume 10% fee or based on ticket assert_equal 1000, earning.fee_cents assert earning.pending? end test "recalculation on full refund" do earning = earnings(:one) earning.amount_cents = 1000 earning.fee_cents = 100 earning.save! # Assume all tickets in order refunded order = orders(:one) order.tickets.each { |t| t.update!(status: "refunded") } earning.recalculate_on_refund(order) assert_equal 0, earning.amount_cents assert earning.refunded? # Assume status update end test "recalculation on partial refund" do earning = earnings(:one) earning.amount_cents = 2000 earning.fee_cents = 200 earning.save! order = orders(:one) # Refund one ticket of 1000 order.tickets.first.update!(status: "refunded") earning.recalculate_on_refund(order) assert_equal 1000, earning.amount_cents # Half assert_equal 100, earning.fee_cents # Half end end