user upgrades: add ability to refund upgrades.
This commit is contained in:
@@ -27,6 +27,14 @@ class UserUpgradesController < ApplicationController
|
||||
respond_with(@user_upgrade)
|
||||
end
|
||||
|
||||
def refund
|
||||
@user_upgrade = authorize UserUpgrade.find(params[:id])
|
||||
@user_upgrade.refund!
|
||||
flash[:notice] = "Upgrade refunded"
|
||||
|
||||
respond_with(@user_upgrade)
|
||||
end
|
||||
|
||||
def receipt
|
||||
@user_upgrade = authorize UserUpgrade.find(params[:id])
|
||||
redirect_to @user_upgrade.receipt_url
|
||||
|
||||
@@ -11,7 +11,8 @@ class UserUpgrade < ApplicationRecord
|
||||
enum status: {
|
||||
pending: 0,
|
||||
processing: 10,
|
||||
complete: 20
|
||||
complete: 20,
|
||||
refunded: 30,
|
||||
}
|
||||
|
||||
scope :gifted, -> { where("recipient_id != purchaser_id") }
|
||||
@@ -62,6 +63,19 @@ class UserUpgrade < ApplicationRecord
|
||||
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 upgrade_price
|
||||
case upgrade_type
|
||||
when "gold"
|
||||
@@ -120,7 +134,7 @@ class UserUpgrade < ApplicationRecord
|
||||
concerning :UpgradeMethods do
|
||||
def process_upgrade!(payment_status)
|
||||
recipient.with_lock do
|
||||
return if status == "complete"
|
||||
return unless pending? || processing?
|
||||
|
||||
if payment_status == "paid"
|
||||
upgrade_recipient!
|
||||
@@ -198,24 +212,38 @@ class UserUpgrade < ApplicationRecord
|
||||
checkout
|
||||
end
|
||||
|
||||
def refund!(reason: nil)
|
||||
with_lock do
|
||||
return if refunded?
|
||||
|
||||
Stripe::Refund.create(payment_intent: payment_intent.id, reason: reason)
|
||||
recipient.update!(level: previous_level)
|
||||
update!(status: "refunded")
|
||||
end
|
||||
end
|
||||
|
||||
def receipt_url
|
||||
return nil if pending? || stripe_id.nil?
|
||||
|
||||
checkout_session = Stripe::Checkout::Session.retrieve(stripe_id)
|
||||
payment_intent = Stripe::PaymentIntent.retrieve(checkout_session.payment_intent)
|
||||
charge = payment_intent.charges.data.first
|
||||
charge.receipt_url
|
||||
end
|
||||
|
||||
def payment_url
|
||||
return nil if pending? || stripe_id.nil?
|
||||
|
||||
checkout_session = Stripe::Checkout::Session.retrieve(stripe_id)
|
||||
payment_intent = Stripe::PaymentIntent.retrieve(checkout_session.payment_intent)
|
||||
|
||||
"https://dashboard.stripe.com/payments/#{payment_intent.id}"
|
||||
end
|
||||
|
||||
def checkout_session
|
||||
@checkout_session ||= Stripe::Checkout::Session.retrieve(stripe_id)
|
||||
end
|
||||
|
||||
def payment_intent
|
||||
@payment_intent ||= Stripe::PaymentIntent.retrieve(checkout_session.payment_intent)
|
||||
end
|
||||
|
||||
def charge
|
||||
payment_intent.charges.data.first
|
||||
end
|
||||
|
||||
def has_receipt?
|
||||
!pending?
|
||||
end
|
||||
|
||||
@@ -11,6 +11,10 @@ class UserUpgradePolicy < ApplicationPolicy
|
||||
record.recipient == user || record.purchaser == user || user.is_owner?
|
||||
end
|
||||
|
||||
def refund?
|
||||
user.is_owner? && record.complete?
|
||||
end
|
||||
|
||||
def receipt?
|
||||
(record.purchaser == user || user.is_owner?) && record.has_receipt?
|
||||
end
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
<% if policy(user_upgrade).payment? %>
|
||||
| <%= link_to "Payment", payment_user_upgrade_path(user_upgrade), target: "_blank" %>
|
||||
<% end %>
|
||||
<% if policy(user_upgrade).refund? %>
|
||||
| <%= link_to "Refund", refund_user_upgrade_path(user_upgrade), remote: true, method: :put, "data-confirm": "Are you sure you want to refund this payment?" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
|
||||
1
app/views/user_upgrades/refund.js.erb
Normal file
1
app/views/user_upgrades/refund.js.erb
Normal file
@@ -0,0 +1 @@
|
||||
location.reload();
|
||||
@@ -257,6 +257,7 @@ Rails.application.routes.draw do
|
||||
resources :user_upgrades, only: [:new, :create, :show, :index] do
|
||||
get :receipt, on: :member
|
||||
get :payment, on: :member
|
||||
put :refund, on: :member
|
||||
end
|
||||
resources :user_feedbacks, except: [:destroy]
|
||||
resources :user_name_change_requests, only: [:new, :create, :show, :index]
|
||||
|
||||
@@ -183,6 +183,51 @@ class UserUpgradesControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
end
|
||||
|
||||
context "refund action" do
|
||||
mock_stripe!
|
||||
|
||||
context "for a self upgrade" do
|
||||
context "to Gold" do
|
||||
should_eventually "refund the upgrade" do
|
||||
@user_upgrade = create(:self_gold_upgrade, recipient: create(:gold_user), status: "complete")
|
||||
@user_upgrade.create_checkout!
|
||||
|
||||
put_auth refund_user_upgrade_path(@user_upgrade), create(:owner_user), xhr: true
|
||||
|
||||
assert_response :success
|
||||
assert_equal("refunded", @user_upgrade.reload.status)
|
||||
assert_equal(User::Levels::MEMBER, @user_upgrade.recipient.level)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "for a gifted upgrade" do
|
||||
context "to Platinum" do
|
||||
should_eventually "refund the upgrade" do
|
||||
@user_upgrade = create(:gift_platinum_upgrade, recipient: create(:platinum_user), status: "complete")
|
||||
@user_upgrade.create_checkout!
|
||||
|
||||
put_auth refund_user_upgrade_path(@user_upgrade), create(:owner_user), xhr: true
|
||||
|
||||
assert_response :success
|
||||
assert_equal("refunded", @user_upgrade.reload.status)
|
||||
assert_equal(User::Levels::MEMBER, @user_upgrade.recipient.level)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
should "not allow unauthorized users to create a refund" do
|
||||
@user_upgrade = create(:self_gold_upgrade, recipient: create(:gold_user), status: "complete")
|
||||
@user_upgrade.create_checkout!
|
||||
|
||||
put_auth refund_user_upgrade_path(@user_upgrade), @user_upgrade.purchaser, xhr: true
|
||||
|
||||
assert_response 403
|
||||
assert_equal("complete", @user_upgrade.reload.status)
|
||||
assert_equal(User::Levels::GOLD, @user_upgrade.recipient.level)
|
||||
end
|
||||
end
|
||||
|
||||
context "create action" do
|
||||
mock_stripe!
|
||||
|
||||
|
||||
@@ -82,5 +82,16 @@ class UserUpgradeTest < ActiveSupport::TestCase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "the #refund! method" do
|
||||
should_eventually "refund a Gold upgrade" do
|
||||
@user_upgrade = create(:self_gold_upgrade, recipient: create(:gold_user), status: "complete")
|
||||
@user_upgrade.create_checkout!
|
||||
@user_upgrade.refund!
|
||||
|
||||
assert_equal("refunded", @user_upgrade.reload.status)
|
||||
assert_equal(User::Levels::MEMBER, @user_upgrade.recipient.level)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user