1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-12-01 12:24:28 +01:00

[bug] wallet usage is noted on subscription invoices even if wallet was not used + use payment confirm API for subscriptions only (sca)

This commit is contained in:
Sylvain 2019-09-10 17:57:46 +02:00
parent 4d0ac9b3ca
commit ac0489a496
7 changed files with 75 additions and 68 deletions

View File

@ -246,6 +246,14 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
// Used in wallet info template to interpolate some translations
$scope.numberFilter = $filter('number');
// Cart items
$scope.cartItems = {
coupon_code: ((coupon ? coupon.code : undefined)),
subscription: {
plan_id: selectedPlan.id
}
};
// retrieve the CGV
CustomAsset.get({ name: 'cgv-file' }, function (cgv) { $scope.cgv = cgv.custom_asset; });
@ -254,29 +262,8 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
* Handle the stripe's card tokenization process response and save the subscription to the API with the
* card token just created.
*/
$scope.payment = function (status, response) {
if (response.error) {
growl.error(response.error.message);
} else {
$scope.attempting = true;
Subscription.save({
coupon_code: ((coupon ? coupon.code : undefined)),
subscription: {
plan_id: selectedPlan.id,
user_id: member.id,
card_token: response.id
}
}
, function (data) { // success
$uibModalInstance.close(data);
}
, function (data, status) { // failed
$scope.alerts = [];
$scope.alerts.push({ msg: _t('an_error_occured_during_the_payment_process_please_try_again_later'), type: 'danger' });
$scope.attempting = false;
}
);
}
$scope.onPaymentSuccess = function (response) {
$uibModalInstance.close(response);
};
}
]
@ -367,7 +354,7 @@ Application.Controllers.controller('PlansIndexController', ['$scope', '$rootScop
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
}
]
}).result['finally'](null).then(function (reservation) {
}).result['finally'](null).then(function (subscription) {
$scope.ctrl.member.subscribed_plan = angular.copy($scope.selectedPlan);
Auth._currentUser.subscribed_plan = angular.copy($scope.selectedPlan);
$scope.ctrl.member = null;

View File

@ -19,28 +19,32 @@ class API::PaymentsController < API::ApiController
end
# Compute the price
reservable = cart_items_params[:reservable_type].constantize.find(cart_items_params[:reservable_id])
price_details = Price.compute(false,
current_user,
reservable,
cart_items_params[:slots_attributes] || [],
cart_items_params[:plan_id],
cart_items_params[:nb_reserve_places],
cart_items_params[:tickets_attributes],
coupon_params[:coupon_code])
# Subtract wallet amount from total
total = price_details[:total]
wallet_debit = get_wallet_debit(current_user, total)
if params[:cart_items][:reservation]
reservable = cart_items_params[:reservable_type].constantize.find(cart_items_params[:reservable_id])
price_details = Price.compute(false,
current_user,
reservable,
cart_items_params[:slots_attributes] || [],
cart_items_params[:plan_id],
cart_items_params[:nb_reserve_places],
cart_items_params[:tickets_attributes],
coupon_params[:coupon_code])
# Subtract wallet amount from total
total = price_details[:total]
wallet_debit = get_wallet_debit(current_user, total)
amount = total - wallet_debit
elsif params[:cart_items][:subscription]
amount = 2000 # TODO
end
# Create the PaymentIntent
intent = Stripe::PaymentIntent.create(
payment_method: params[:payment_method_id],
amount: total - wallet_debit,
amount: amount,
currency: Rails.application.secrets.stripe_currency,
confirmation_method: 'manual',
confirm: true,
customer: current_user.stp_customer_id,
customer: current_user.stp_customer_id
)
elsif params[:payment_intent_id].present?
intent = Stripe::PaymentIntent.confirm(params[:payment_intent_id])
@ -48,20 +52,26 @@ class API::PaymentsController < API::ApiController
rescue Stripe::CardError => e
# Display error on client
render(status: 200, json: { error: e.message }) and return
rescue InvalidCouponError
render(json: { coupon_code: 'wrong coupon code or expired' }, status: :unprocessable_entity) and return
end
if intent.status == 'succeeded'
if params[:cart_items][:reservation]
render(on_reservation_success(intent)) and return
elsif params[:cart_items][:subscription]
render(on_subscription_success(intent)) and return
end
end
render(on_payment_success(intent)) and return if intent.status == 'succeeded'
render generate_payment_response(intent)
end
private
def on_payment_success(intent)
# TODO create subscription is needed
user_id = params[:cart_items][:reservation][:user_id]
def on_reservation_success(intent)
@reservation = Reservation.new(reservation_params)
is_reserve = Reservations::Reserve.new(user_id, current_user.invoicing_profile.id)
is_reserve = Reservations::Reserve.new(current_user.id, current_user.invoicing_profile.id)
.pay_and_save(@reservation, coupon: coupon_params[:coupon_code], payment_intent_id: intent.id)
Stripe::PaymentIntent.update(
intent.id,
@ -75,8 +85,23 @@ class API::PaymentsController < API::ApiController
else
{ json: @reservation.errors, status: :unprocessable_entity }
end
rescue InvalidCouponError
{ json: { coupon_code: 'wrong coupon code or expired' }, status: :unprocessable_entity }
end
def on_subscription_success(intent)
@subscription = Subscription.new(subscription_params)
is_subscribe = Subscriptions::Subscribe.new(current_user.invoicing_profile.id, current_user.id)
.pay_and_save(@subscription, coupon: coupon_params[:coupon_code], invoice: true, payment_intent_id: intent.id)
Stripe::PaymentIntent.update(
intent.id,
description: "Invoice reference: #{@subscription.invoices.first.reference}"
)
if is_subscribe
{ template: 'api/subscriptions/show', status: :created, location: @subscription }
else
{ json: @subscription.errors, status: :unprocessable_entity }
end
end
def generate_payment_response(intent)
@ -110,6 +135,10 @@ class API::PaymentsController < API::ApiController
slots_attributes: %i[id start_at end_at availability_id offered])
end
def subscription_params
params[:cart_items].require(:subscription).permit(:plan_id)
end
def cart_items_params
params[:cart_items].require(:reservation).permit(:reservable_id, :reservable_type, :plan_id, :user_id, :nb_reserve_places,
tickets_attributes: %i[event_price_category_id booked],

View File

@ -57,7 +57,7 @@ class API::ReservationsController < API::ApiController
end
def reservation_params
params.require(:reservation).permit(:message, :reservable_id, :reservable_type, :card_token, :plan_id, :nb_reserve_places,
params.require(:reservation).permit(:message, :reservable_id, :reservable_type, :plan_id, :nb_reserve_places,
tickets_attributes: %i[event_price_category_id booked],
slots_attributes: %i[id start_at end_at availability_id offered])
end

View File

@ -16,7 +16,7 @@ class API::SubscriptionsController < API::ApiController
@subscription = Subscription.new(subscription_params)
is_subscribe = Subscriptions::Subscribe.new(current_user.invoicing_profile.id, user_id)
.pay_and_save(@subscription, coupon_params[:coupon_code], true)
.pay_and_save(@subscription, coupon: coupon_params[:coupon_code], invoice: true)
if is_subscribe
render :show, status: :created, location: @subscription
@ -51,7 +51,7 @@ class API::SubscriptionsController < API::ApiController
# Never trust parameters from the scary internet, only allow the white list through.
def subscription_params
params.require(:subscription).permit(:plan_id, :card_token)
params.require(:subscription).permit(:plan_id)
end
def coupon_params
@ -61,12 +61,4 @@ class API::SubscriptionsController < API::ApiController
def subscription_update_params
params.require(:subscription).permit(:expired_at)
end
# TODO, refactor subscriptions logic and move this in model/validator
def valid_card_token?(token)
Stripe::Token.retrieve(token)
rescue Stripe::InvalidRequestError => e
@subscription.errors[:card_token] << e.message
false
end
end

View File

@ -18,7 +18,7 @@ class Reservation < ActiveRecord::Base
validate :machine_not_already_reserved, if: -> { reservable.is_a?(Machine) }
validate :training_not_fully_reserved, if: -> { reservable.is_a?(Training) }
attr_accessor :card_token, :plan_id, :subscription
attr_accessor :plan_id, :subscription
after_commit :notify_member_create_reservation, on: :create
after_commit :notify_admin_member_create_reservation, on: :create

View File

@ -13,8 +13,6 @@ class Subscription < ActiveRecord::Base
validates_presence_of :plan_id
validates_with SubscriptionGroupValidator
attr_accessor :card_token
# creation
after_save :notify_member_subscribed_plan
after_save :notify_admin_subscribed_plan
@ -22,7 +20,7 @@ class Subscription < ActiveRecord::Base
# @param invoice if true then only the subscription is payed, without reservation
# if false then the subscription is payed with reservation
def save_with_payment(operator_profile_id, invoice = true, coupon_code = nil)
def save_with_payment(operator_profile_id, invoice = true, coupon_code = nil, payment_intent_id = nil)
return false unless valid?
set_expiration_date
@ -35,7 +33,7 @@ class Subscription < ActiveRecord::Base
# debit wallet
wallet_transaction = debit_user_wallet
invoc = generate_invoice(operator_profile_id, coupon_code)
invoc = generate_invoice(operator_profile_id, coupon_code, payment_intent_id)
if wallet_transaction
invoc.wallet_amount = @wallet_amount_debit
invoc.wallet_transaction_id = wallet_transaction.id
@ -45,7 +43,7 @@ class Subscription < ActiveRecord::Base
true
end
def generate_invoice(operator_profile_id, coupon_code = nil)
def generate_invoice(operator_profile_id, coupon_code = nil, payment_intent_id = nil)
coupon_id = nil
total = plan.amount
@ -65,7 +63,8 @@ class Subscription < ActiveRecord::Base
statistic_profile: user.statistic_profile,
total: total,
coupon_id: coupon_id,
operator_profile_id: operator_profile_id
operator_profile_id: operator_profile_id,
stp_payment_intent_id: payment_intent_id
)
invoice.invoice_items.push InvoiceItem.new(
amount: plan.amount,
@ -194,7 +193,7 @@ class Subscription < ActiveRecord::Base
end
def debit_user_wallet
return unless @wallet_amount_debit.present? || @wallet_amount_debit.zero?
return if !@wallet_amount_debit.present? || @wallet_amount_debit.zero?
amount = @wallet_amount_debit / 100.0
WalletService.new(user: user, wallet: user.wallet).debit(amount, self)

View File

@ -9,11 +9,11 @@ class Subscriptions::Subscribe
@operator_profile_id = operator_profile_id
end
def pay_and_save(subscription, coupon, invoice)
def pay_and_save(subscription, coupon: nil, invoice: nil, payment_intent_id: nil)
return false if user_id.nil?
subscription.statistic_profile_id = StatisticProfile.find_by(user_id: user_id).id
subscription.save_with_payment(operator_profile_id, invoice, coupon)
subscription.save_with_payment(operator_profile_id, invoice, coupon, payment_intent_id)
end
def extend_subscription(subscription, new_expiration_date, free_days)