Factor out the Stripe code from the UserUpgrade class. Introduce a new PaymentTransaction abstract class that represents a payment with some payment processor, and a PaymentTransaction::Stripe class that implements transactions with Stripe. Note that we can't completely eliminate Stripe even though we no longer accept payments with it because we still need to be able to look up old payments in Stripe.
168 lines
3.6 KiB
Ruby
168 lines
3.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class UserUpgrade < ApplicationRecord
|
|
belongs_to :recipient, class_name: "User"
|
|
belongs_to :purchaser, class_name: "User"
|
|
|
|
delegate :payment_url, :receipt_url, to: :transaction
|
|
|
|
enum upgrade_type: {
|
|
gold: 0,
|
|
platinum: 10,
|
|
gold_to_platinum: 20,
|
|
}, _suffix: "upgrade"
|
|
|
|
enum status: {
|
|
pending: 0,
|
|
processing: 10,
|
|
complete: 20,
|
|
refunded: 30,
|
|
}
|
|
|
|
scope :gifted, -> { where("recipient_id != purchaser_id") }
|
|
scope :self_upgrade, -> { where("recipient_id = purchaser_id") }
|
|
|
|
def self.enabled?
|
|
Danbooru.config.user_upgrades_enabled?
|
|
end
|
|
|
|
def self.gold_price
|
|
if Danbooru.config.is_promotion?
|
|
1500
|
|
else
|
|
2000
|
|
end
|
|
end
|
|
|
|
def self.platinum_price
|
|
2 * gold_price
|
|
end
|
|
|
|
def self.gold_to_platinum_price
|
|
platinum_price - gold_price
|
|
end
|
|
|
|
def level
|
|
case upgrade_type
|
|
when "gold"
|
|
User::Levels::GOLD
|
|
when "platinum"
|
|
User::Levels::PLATINUM
|
|
when "gold_to_platinum"
|
|
User::Levels::PLATINUM
|
|
else
|
|
raise NotImplementedError
|
|
end
|
|
end
|
|
|
|
def previous_level
|
|
case upgrade_type
|
|
when "gold"
|
|
User::Levels::MEMBER
|
|
when "platinum"
|
|
User::Levels::MEMBER
|
|
when "gold_to_platinum"
|
|
User::Levels::GOLD
|
|
else
|
|
raise NotImplementedError
|
|
end
|
|
end
|
|
|
|
def level_string
|
|
User.level_string(level)
|
|
end
|
|
|
|
def is_gift?
|
|
recipient != purchaser
|
|
end
|
|
|
|
def self.visible(user)
|
|
if user.is_owner?
|
|
all
|
|
else
|
|
where(recipient: user).or(where(purchaser: user))
|
|
end
|
|
end
|
|
|
|
def self.search(params)
|
|
q = search_attributes(params, :id, :created_at, :updated_at, :upgrade_type, :status, :stripe_id, :recipient, :purchaser)
|
|
|
|
if params[:is_gifted].to_s.truthy?
|
|
q = q.gifted
|
|
elsif params[:is_gifted].to_s.falsy?
|
|
q = q.self_upgrade
|
|
end
|
|
|
|
q.apply_default_order(params)
|
|
end
|
|
|
|
concerning :UpgradeMethods do
|
|
def process_upgrade!(payment_status)
|
|
recipient.with_lock do
|
|
return unless pending? || processing?
|
|
|
|
if payment_status == "paid"
|
|
upgrade_recipient!
|
|
dmail_recipient!
|
|
dmail_purchaser!
|
|
update!(status: :complete)
|
|
else
|
|
update!(status: :processing)
|
|
end
|
|
end
|
|
end
|
|
|
|
def upgrade_recipient!
|
|
recipient.update!(level: level)
|
|
end
|
|
|
|
def dmail_recipient!
|
|
if is_gift?
|
|
body = "Congratulations, your account has been upgraded to #{level_string} by <@#{purchaser.name}>. Enjoy!"
|
|
else
|
|
body = "You are now a #{level_string} user. Thanks for supporting #{Danbooru.config.canonical_app_name}!"
|
|
end
|
|
|
|
title = "You have been upgraded to #{level_string}!"
|
|
Dmail.create_automated(to: recipient, title: title, body: body)
|
|
end
|
|
|
|
def dmail_purchaser!
|
|
return unless is_gift?
|
|
|
|
title = "#{recipient.name} has been upgraded to #{level_string}!"
|
|
body = "<@#{recipient.name}> is now a #{level_string} user. Thanks for supporting #{Danbooru.config.canonical_app_name}!"
|
|
|
|
Dmail.create_automated(to: purchaser, title: title, body: body)
|
|
end
|
|
end
|
|
|
|
concerning :TransactionMethods do
|
|
def create_checkout!(country: "US", allow_promotion_codes: false)
|
|
transaction.create!(country: country, allow_promotion_codes: allow_promotion_codes)
|
|
end
|
|
|
|
def refund!(reason: nil)
|
|
with_lock do
|
|
return if refunded?
|
|
|
|
transaction.refund!(reason)
|
|
recipient.update!(level: previous_level)
|
|
update!(status: "refunded")
|
|
end
|
|
end
|
|
|
|
def transaction
|
|
PaymentTransaction::Stripe.new(self)
|
|
end
|
|
|
|
def has_receipt?
|
|
!pending?
|
|
end
|
|
|
|
def has_payment?
|
|
!pending?
|
|
end
|
|
end
|
|
end
|