require "test_helper" class PayoutFlowTest < ActionDispatch::IntegrationTest setup do @promoter = User.create!(email: "promoter@example.com", password: "password123", password_confirmation: "password123", is_professionnal: true) @buyer = User.create!(email: "buyer@example.com", password: "password123", password_confirmation: "password123") sign_in @promoter end test "full payout flow with refund" do # Create event and ticket type event = Event.create!(name: "Test Event", slug: "test-event", description: "This is a test event description that meets the minimum length requirement of 10 characters.", venue_name: "Venue", venue_address: "Address", latitude: 48.0, longitude: 2.0, start_time: 1.day.ago, end_time: 1.hour.ago, user: @promoter, state: :published) ticket_type = TicketType.create!(event: event, name: "Standard", price_cents: 1000, quantity: 10, sale_start_at: 2.days.ago, sale_end_at: Time.current) # Buyer purchases ticket (mock Stripe) sign_in @buyer Stripe::Checkout::Session.expects(:create).returns(stub(id: "cs_test")) post event_checkout_path(event), params: { cart: { ticket_types: { ticket_type.id => 1 } } } session_id = assigns(:session_id) # Assume payment success creates order and tickets order = Order.last ticket = Ticket.last assert_equal "paid", order.status assert_equal "active", ticket.status # Earnings created earning = Earning.last assert_not_nil earning assert_equal 900, earning.amount_cents # Refund one ticket sign_in @promoter ticket.update!(status: "refunded") earning.reload assert_equal 0, earning.amount_cents # Recalculated # Request payout assert event.can_request_payout?(@promoter) post promoter_payouts_path, params: { event_id: event.id } payout = Payout.last assert_equal :pending, payout.status # Admin process admin = User.create!(email: "admin@example.com", password: "password123", password_confirmation: "password123") admin.add_role :admin sign_in admin Stripe::Transfer.expects(:create).returns(stub(id: "tr_success")) patch admin_payout_path(payout) payout.reload assert_equal :completed, payout.status # Webhook succeeds post stripe_webhooks_path, params: { type: "payout.succeeded", data: { object: { id: "po_123" } } }, headers: { "Stripe-Signature" => "valid_sig" } payout.reload assert_equal :completed, payout.status # Confirmed end end