feat: Implement promoter payout system for event revenue processing

- Add Payout model with associations to User and Event
- Create payout requests for completed events with proper earnings calculation
- Exclude refunded tickets from payout calculations
- Add promoter dashboard views for managing payouts
- Implement admin interface for processing payouts
- Integrate with Stripe for actual payment processing
- Add comprehensive tests for payout functionality

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
kbe
2025-09-17 00:29:20 +02:00
parent 58141dca94
commit 59e1854803
20 changed files with 587 additions and 254 deletions

59
app/models/payout.rb Normal file
View File

@@ -0,0 +1,59 @@
class Payout < ApplicationRecord
# === Relations ===
belongs_to :user
belongs_to :event
# === Enums ===
enum :status, {
pending: 0, # Payout requested but not processed
processing: 1, # Payout being processed
completed: 2, # Payout successfully completed
failed: 3 # Payout failed
}, default: :pending
# === Validations ===
validates :amount_cents, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :fee_cents, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :status, presence: true
validates :total_orders_count, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :refunded_orders_count, presence: true, numericality: { greater_than_or_equal_to: 0 }
validates :stripe_payout_id, allow_blank: true, uniqueness: true
# === Scopes ===
scope :completed, -> { where(status: :completed) }
scope :pending, -> { where(status: :pending) }
scope :processing, -> { where(status: :processing) }
# === Instance Methods ===
# Amount in euros (formatted)
def amount_euros
amount_cents / 100.0
end
# Fee in euros (formatted)
def fee_euros
fee_cents / 100.0
end
# Net amount after fees
def net_amount_cents
amount_cents - fee_cents
end
# Net amount in euros
def net_amount_euros
net_amount_cents / 100.0
end
# Check if payout can be processed
def can_process?
pending? && amount_cents > 0
end
# Process the payout through Stripe
def process_payout!
service = PayoutService.new(self)
service.process!
end
end