user upgrades: add ability to refund upgrades.
This commit is contained in:
@@ -27,6 +27,14 @@ class UserUpgradesController < ApplicationController
|
|||||||
respond_with(@user_upgrade)
|
respond_with(@user_upgrade)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def refund
|
||||||
|
@user_upgrade = authorize UserUpgrade.find(params[:id])
|
||||||
|
@user_upgrade.refund!
|
||||||
|
flash[:notice] = "Upgrade refunded"
|
||||||
|
|
||||||
|
respond_with(@user_upgrade)
|
||||||
|
end
|
||||||
|
|
||||||
def receipt
|
def receipt
|
||||||
@user_upgrade = authorize UserUpgrade.find(params[:id])
|
@user_upgrade = authorize UserUpgrade.find(params[:id])
|
||||||
redirect_to @user_upgrade.receipt_url
|
redirect_to @user_upgrade.receipt_url
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ class UserUpgrade < ApplicationRecord
|
|||||||
enum status: {
|
enum status: {
|
||||||
pending: 0,
|
pending: 0,
|
||||||
processing: 10,
|
processing: 10,
|
||||||
complete: 20
|
complete: 20,
|
||||||
|
refunded: 30,
|
||||||
}
|
}
|
||||||
|
|
||||||
scope :gifted, -> { where("recipient_id != purchaser_id") }
|
scope :gifted, -> { where("recipient_id != purchaser_id") }
|
||||||
@@ -62,6 +63,19 @@ class UserUpgrade < ApplicationRecord
|
|||||||
end
|
end
|
||||||
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
|
def upgrade_price
|
||||||
case upgrade_type
|
case upgrade_type
|
||||||
when "gold"
|
when "gold"
|
||||||
@@ -120,7 +134,7 @@ class UserUpgrade < ApplicationRecord
|
|||||||
concerning :UpgradeMethods do
|
concerning :UpgradeMethods do
|
||||||
def process_upgrade!(payment_status)
|
def process_upgrade!(payment_status)
|
||||||
recipient.with_lock do
|
recipient.with_lock do
|
||||||
return if status == "complete"
|
return unless pending? || processing?
|
||||||
|
|
||||||
if payment_status == "paid"
|
if payment_status == "paid"
|
||||||
upgrade_recipient!
|
upgrade_recipient!
|
||||||
@@ -198,24 +212,38 @@ class UserUpgrade < ApplicationRecord
|
|||||||
checkout
|
checkout
|
||||||
end
|
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
|
def receipt_url
|
||||||
return nil if pending? || stripe_id.nil?
|
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
|
charge.receipt_url
|
||||||
end
|
end
|
||||||
|
|
||||||
def payment_url
|
def payment_url
|
||||||
return nil if pending? || stripe_id.nil?
|
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}"
|
"https://dashboard.stripe.com/payments/#{payment_intent.id}"
|
||||||
end
|
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?
|
def has_receipt?
|
||||||
!pending?
|
!pending?
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ class UserUpgradePolicy < ApplicationPolicy
|
|||||||
record.recipient == user || record.purchaser == user || user.is_owner?
|
record.recipient == user || record.purchaser == user || user.is_owner?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def refund?
|
||||||
|
user.is_owner? && record.complete?
|
||||||
|
end
|
||||||
|
|
||||||
def receipt?
|
def receipt?
|
||||||
(record.purchaser == user || user.is_owner?) && record.has_receipt?
|
(record.purchaser == user || user.is_owner?) && record.has_receipt?
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -40,6 +40,9 @@
|
|||||||
<% if policy(user_upgrade).payment? %>
|
<% if policy(user_upgrade).payment? %>
|
||||||
| <%= link_to "Payment", payment_user_upgrade_path(user_upgrade), target: "_blank" %>
|
| <%= link_to "Payment", payment_user_upgrade_path(user_upgrade), target: "_blank" %>
|
||||||
<% end %>
|
<% 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 %>
|
||||||
<% 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
|
resources :user_upgrades, only: [:new, :create, :show, :index] do
|
||||||
get :receipt, on: :member
|
get :receipt, on: :member
|
||||||
get :payment, on: :member
|
get :payment, on: :member
|
||||||
|
put :refund, on: :member
|
||||||
end
|
end
|
||||||
resources :user_feedbacks, except: [:destroy]
|
resources :user_feedbacks, except: [:destroy]
|
||||||
resources :user_name_change_requests, only: [:new, :create, :show, :index]
|
resources :user_name_change_requests, only: [:new, :create, :show, :index]
|
||||||
|
|||||||
@@ -183,6 +183,51 @@ class UserUpgradesControllerTest < ActionDispatch::IntegrationTest
|
|||||||
end
|
end
|
||||||
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
|
context "create action" do
|
||||||
mock_stripe!
|
mock_stripe!
|
||||||
|
|
||||||
|
|||||||
@@ -82,5 +82,16 @@ class UserUpgradeTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user