# 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, } enum payment_processor: { stripe: 0, authorize_net: 100, shopify: 200, upgrade_code: 300, } scope :gifted, -> { where("recipient_id != purchaser_id") } scope :self_upgrade, -> { where("recipient_id = purchaser_id") } def self.enabled? Danbooru.config.user_upgrades_enabled?.to_s.truthy? end def self.gold_price if Danbooru.config.is_promotion? 15.00 else 20.00 end end def self.platinum_price 2 * gold_price end def self.gold_to_platinum_price platinum_price - gold_price end def price case upgrade_type in "gold" UserUpgrade.gold_price in "platinum" UserUpgrade.platinum_price in "gold_to_platinum" UserUpgrade.gold_to_platinum_price end 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, current_user) q = search_attributes(params, [:id, :created_at, :updated_at, :upgrade_type, :status, :transaction_id, :payment_processor, :recipient, :purchaser], current_user: current_user) 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 = "paid") 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 case payment_processor in "stripe" PaymentTransaction::Stripe.new(self) in "authorize_net" PaymentTransaction::AuthorizeNet.new(self) in "shopify" PaymentTransaction::Shopify.new(self) end end def has_receipt? !pending? end def has_payment? !pending? end end end