mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-28 09:24:24 +01:00
WIP: array of items
Migration from cart_items:{reservation:{}, subscription:{}, ...} to cart_items:{items:[{reservation:{}, ...}], ...}
This commit is contained in:
parent
dd1d05cc3a
commit
66f81a975e
@ -12,7 +12,9 @@
|
||||
- Fix a bug: unable to cancel the upgrade before it begins
|
||||
- Fix a bug: unable to use run.fab.mn
|
||||
- Fix a bug: typo in allow/prevent booking overlapping slots
|
||||
- Fix a bug: in the admin calendar, the trainings' info panel shows "duration: null minutes"
|
||||
- `SUPERADMIN_EMAIL` renamed to `ADMINSYS_EMAIL`
|
||||
- `scripts/run-tests.sh` renamed to `scripts/tests.sh`
|
||||
- [BREAKING CHANGE] GET `open_api/v1/invoices` won't return `stp_invoice_id` OR `stp_payment_intent_id` anymore. The new field `payment_gateway_object` will contain some similar data if the invoice was paid online by card.
|
||||
- [TODO DEPLOY] `rails fablab:stripe:set_gateway`
|
||||
- [TODO DEPLOY] `rails fablab:maintenance:rebuild_stylesheet`
|
||||
|
26
app/controllers/api/local_payment_controller.rb
Normal file
26
app/controllers/api/local_payment_controller.rb
Normal file
@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# API Controller for handling local payments (at the reception) or when the amount = 0
|
||||
class API::LocalPaymentController < API::PaymentsController
|
||||
def confirm_payment
|
||||
cart = shopping_cart
|
||||
price = debit_amount(cart)
|
||||
|
||||
authorize LocalPaymentContext.new(cart, price[:amount])
|
||||
|
||||
if cart.reservation
|
||||
res = on_reservation_success(nil, nil, price[:details], cart)
|
||||
elsif cart.subscription
|
||||
res = on_subscription_success(nil, nil, price[:details], cart)
|
||||
end
|
||||
|
||||
render res
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def shopping_cart
|
||||
cs = CartService.new(current_user)
|
||||
cs.from_hash(params)
|
||||
end
|
||||
end
|
@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Abstract API Controller to be extended by each gateway, for handling the payments processes in the front-end
|
||||
# Abstract API Controller to be extended by each payment gateway/mean, for handling the payments processes in the front-end
|
||||
class API::PaymentsController < API::ApiController
|
||||
before_action :authenticate_user!
|
||||
|
||||
@ -21,9 +21,7 @@ class API::PaymentsController < API::ApiController
|
||||
wallet_amount >= total_amount ? total_amount : wallet_amount
|
||||
end
|
||||
|
||||
def card_amount
|
||||
cs = CartService.new(current_user)
|
||||
cart = cs.from_hash(params[:cart_items])
|
||||
def debit_amount(cart)
|
||||
price_details = cart.total
|
||||
|
||||
# Subtract wallet amount from total
|
||||
@ -32,30 +30,33 @@ class API::PaymentsController < API::ApiController
|
||||
{ amount: total - wallet_debit, details: price_details }
|
||||
end
|
||||
|
||||
def check_coupon
|
||||
return if coupon_params[:coupon_code].nil?
|
||||
|
||||
coupon = Coupon.find_by(code: coupon_params[:coupon_code])
|
||||
raise InvalidCouponError if coupon.nil? || coupon.status(current_user.id) != 'active'
|
||||
def shopping_cart
|
||||
cs = CartService.new(current_user)
|
||||
cs.from_hash(params[:cart_items])
|
||||
end
|
||||
|
||||
def check_plan
|
||||
plan_id = (cart_items_params[:subscription][:plan_id] if cart_items_params[:subscription])
|
||||
# @param cart {ShoppingCart}
|
||||
def check_coupon(cart)
|
||||
return if cart.coupon.nil?
|
||||
|
||||
return unless plan_id
|
||||
cart.coupon.coupon
|
||||
end
|
||||
|
||||
plan = Plan.find(plan_id)
|
||||
# @param cart {ShoppingCart}
|
||||
def check_plan(cart)
|
||||
return unless cart.subscription
|
||||
|
||||
plan = cart.subscription.plan
|
||||
raise InvalidGroupError if plan.group_id != current_user.group_id
|
||||
end
|
||||
|
||||
def on_reservation_success(gateway_item_id, gateway_item_type, details)
|
||||
@reservation = Reservation.new(reservation_params)
|
||||
if params[:cart_items][:subscription] && params[:cart_items][:subscription][:plan_id]
|
||||
@reservation.plan_id = params[:cart_items][:subscription][:plan_id]
|
||||
end
|
||||
payment_method = params[:cart_items][:reservation][:payment_method] || 'card'
|
||||
def on_reservation_success(gateway_item_id, gateway_item_type, details, cart)
|
||||
@reservation = cart.reservation.to_reservation
|
||||
@reservation.plan_id = cart.subscription.plan.id if cart.subscription
|
||||
|
||||
payment_method = cart.payment_method || 'card'
|
||||
user_id = if current_user.admin? || current_user.manager?
|
||||
params[:cart_items][:reservation][:user_id]
|
||||
cart.customer.id
|
||||
else
|
||||
current_user.id
|
||||
end
|
||||
@ -64,7 +65,7 @@ class API::PaymentsController < API::ApiController
|
||||
payment_details: details,
|
||||
payment_id: gateway_item_id,
|
||||
payment_type: gateway_item_type,
|
||||
schedule: params[:cart_items][:payment_schedule],
|
||||
schedule: cart.payment_schedule.requested,
|
||||
payment_method: payment_method)
|
||||
post_reservation_save(gateway_item_id, gateway_item_type)
|
||||
|
||||
@ -77,10 +78,10 @@ class API::PaymentsController < API::ApiController
|
||||
end
|
||||
end
|
||||
|
||||
def on_subscription_success(gateway_item_id, gateway_item_type, details)
|
||||
@subscription = Subscription.new(subscription_params)
|
||||
def on_subscription_success(gateway_item_id, gateway_item_type, details, cart)
|
||||
@subscription = cart.subscription.to_subscription
|
||||
user_id = if current_user.admin? || current_user.manager?
|
||||
params[:cart_items][:customer_id]
|
||||
cart.customer.id
|
||||
else
|
||||
current_user.id
|
||||
end
|
||||
@ -89,8 +90,8 @@ class API::PaymentsController < API::ApiController
|
||||
payment_details: details,
|
||||
payment_id: gateway_item_id,
|
||||
payment_type: gateway_item_type,
|
||||
schedule: params[:cart_items][:subscription][:payment_schedule],
|
||||
payment_method: 'card')
|
||||
schedule: cart.payment_schedule.requested,
|
||||
payment_method: cart.payment_method || 'card')
|
||||
|
||||
post_subscription_save(gateway_item_id, gateway_item_type)
|
||||
|
||||
@ -100,27 +101,4 @@ class API::PaymentsController < API::ApiController
|
||||
{ json: @subscription.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
|
||||
def reservation_params
|
||||
params[:cart_items].require(:reservation).permit(:reservable_id, :reservable_type, :nb_reserve_places,
|
||||
tickets_attributes: %i[event_price_category_id booked],
|
||||
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.require(:cart_items).permit(subscription: :plan_id,
|
||||
reservation: [
|
||||
:reservable_id, :reservable_type, :nb_reserve_places,
|
||||
tickets_attributes: %i[event_price_category_id booked],
|
||||
slots_attributes: %i[id start_at end_at availability_id offered]
|
||||
])
|
||||
end
|
||||
|
||||
def coupon_params
|
||||
params.require(:cart_items).permit(:coupon_code)
|
||||
end
|
||||
end
|
||||
|
@ -18,8 +18,9 @@ class API::PayzenController < API::PaymentsController
|
||||
end
|
||||
|
||||
def create_payment
|
||||
amount = card_amount
|
||||
@id = PayZen::Helper.generate_ref(cart_items_params, params[:customer_id])
|
||||
cart = shopping_cart
|
||||
amount = debit_amount(cart)
|
||||
@id = PayZen::Helper.generate_ref(params[:cart_items], params[:customer_id])
|
||||
|
||||
client = PayZen::Charge.new
|
||||
@result = client.create_payment(amount: amount[:amount],
|
||||
@ -29,7 +30,7 @@ class API::PayzenController < API::PaymentsController
|
||||
end
|
||||
|
||||
def create_token
|
||||
@id = PayZen::Helper.generate_ref(cart_items_params, params[:customer_id])
|
||||
@id = PayZen::Helper.generate_ref(params[:cart_items], params[:customer_id])
|
||||
client = PayZen::Charge.new
|
||||
@result = client.create_token(order_id: @id,
|
||||
customer: PayZen::Helper.generate_customer(params[:customer_id], current_user.id, params[:cart_items]))
|
||||
@ -46,13 +47,14 @@ class API::PayzenController < API::PaymentsController
|
||||
client = PayZen::Order.new
|
||||
order = client.get(params[:order_id], operation_type: 'DEBIT')
|
||||
|
||||
amount = card_amount
|
||||
cart = shopping_cart
|
||||
amount = debit_amount(cart)
|
||||
|
||||
if order['answer']['transactions'].first['status'] == 'PAID'
|
||||
if params[:cart_items][:reservation]
|
||||
res = on_reservation_success(params[:order_id], amount[:details])
|
||||
elsif params[:cart_items][:subscription]
|
||||
res = on_subscription_success(params[:order_id], amount[:details])
|
||||
if cart.reservation
|
||||
res = on_reservation_success(params[:order_id], amount[:details], cart)
|
||||
elsif cart.subscription
|
||||
res = on_subscription_success(params[:order_id], amount[:details], cart)
|
||||
end
|
||||
end
|
||||
|
||||
@ -63,12 +65,12 @@ class API::PayzenController < API::PaymentsController
|
||||
|
||||
private
|
||||
|
||||
def on_reservation_success(order_id, details)
|
||||
super(order_id, 'PayZen::Order', details)
|
||||
def on_reservation_success(order_id, details, cart)
|
||||
super(order_id, 'PayZen::Order', details, cart)
|
||||
end
|
||||
|
||||
def on_subscription_success(order_id, details)
|
||||
super(order_id, 'PayZen::Order', details)
|
||||
def on_subscription_success(order_id, details, cart)
|
||||
super(order_id, 'PayZen::Order', details, cart)
|
||||
end
|
||||
|
||||
def error_handling
|
||||
|
@ -47,18 +47,4 @@ class API::PricesController < API::ApiController
|
||||
def price_params
|
||||
params.require(:price).permit(:amount)
|
||||
end
|
||||
|
||||
def compute_reservation_price_params
|
||||
params.require(:reservation).permit(:reservable_id, :reservable_type, :plan_id, :user_id, :nb_reserve_places, :payment_schedule,
|
||||
tickets_attributes: %i[event_price_category_id booked],
|
||||
slots_attributes: %i[id start_at end_at availability_id offered])
|
||||
end
|
||||
|
||||
def compute_subscription_price_params
|
||||
params.require(:subscription).permit(:plan_id, :user_id, :payment_schedule)
|
||||
end
|
||||
|
||||
def coupon_params
|
||||
params.permit(:coupon_code)
|
||||
end
|
||||
end
|
||||
|
@ -24,35 +24,6 @@ class API::ReservationsController < API::ApiController
|
||||
|
||||
def show; end
|
||||
|
||||
# Admins can create any reservations. Members can directly create reservations if total = 0,
|
||||
# otherwise, they must use payments_controller#confirm_payment.
|
||||
# Managers can create reservations for other users
|
||||
def create
|
||||
user_id = current_user.admin? || current_user.manager? ? params[:customer_id] : current_user.id
|
||||
price = transaction_amount(user_id)
|
||||
|
||||
authorize ReservationContext.new(Reservation, price[:amount], user_id)
|
||||
|
||||
@reservation = Reservation.new(reservation_params)
|
||||
@reservation.plan_id = params[:subscription][:plan_id] if params[:subscription] && params[:subscription][:plan_id]
|
||||
|
||||
is_reserve = Reservations::Reserve.new(user_id, current_user.invoicing_profile.id)
|
||||
.pay_and_save(@reservation,
|
||||
payment_details: price[:price_details],
|
||||
schedule: params[:payment_schedule],
|
||||
payment_method: params[:payment_method])
|
||||
|
||||
if is_reserve
|
||||
SubscriptionExtensionAfterReservation.new(@reservation).extend_subscription_if_eligible
|
||||
|
||||
render :show, status: :created, location: @reservation
|
||||
else
|
||||
render json: @reservation.errors, status: :unprocessable_entity
|
||||
end
|
||||
rescue InvalidCouponError
|
||||
render json: { coupon_code: 'wrong coupon code or expired' }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def update
|
||||
authorize @reservation
|
||||
if @reservation.update(reservation_params)
|
||||
@ -64,30 +35,6 @@ class API::ReservationsController < API::ApiController
|
||||
|
||||
private
|
||||
|
||||
def transaction_amount(user_id)
|
||||
user = User.find(user_id)
|
||||
cs = CartService.new(current_user)
|
||||
cart = cs.from_hash(customer_id: user_id,
|
||||
subscription: {
|
||||
plan_id: params[:subscription] ? params[:subscription][:plan_id] : nil
|
||||
},
|
||||
reservation: reservation_params,
|
||||
coupon_code: coupon_params[:coupon_code],
|
||||
payment_schedule: params[:payment_schedule])
|
||||
price_details = cart.total
|
||||
|
||||
# Subtract wallet amount from total
|
||||
total = price_details[:total]
|
||||
wallet_debit = get_wallet_debit(user, total)
|
||||
|
||||
{ price_details: price_details, amount: (total - wallet_debit) }
|
||||
end
|
||||
|
||||
def get_wallet_debit(user, total_amount)
|
||||
wallet_amount = (user.wallet.amount * 100).to_i
|
||||
wallet_amount >= total_amount ? total_amount : wallet_amount
|
||||
end
|
||||
|
||||
def set_reservation
|
||||
@reservation = Reservation.find(params[:id])
|
||||
end
|
||||
@ -97,8 +44,4 @@ class API::ReservationsController < API::ApiController
|
||||
tickets_attributes: %i[event_price_category_id booked],
|
||||
slots_attributes: %i[id start_at end_at availability_id offered])
|
||||
end
|
||||
|
||||
def coupon_params
|
||||
params.permit(:coupon_code)
|
||||
end
|
||||
end
|
||||
|
@ -16,11 +16,12 @@ class API::StripeController < API::PaymentsController
|
||||
intent = nil # stripe's payment intent
|
||||
res = nil # json of the API answer
|
||||
|
||||
cart = shopping_cart
|
||||
begin
|
||||
amount = card_amount
|
||||
amount = debit_amount(cart)
|
||||
if params[:payment_method_id].present?
|
||||
check_coupon
|
||||
check_plan
|
||||
check_coupon(cart)
|
||||
check_plan(cart)
|
||||
|
||||
# Create the PaymentIntent
|
||||
intent = Stripe::PaymentIntent.create(
|
||||
@ -46,10 +47,10 @@ class API::StripeController < API::PaymentsController
|
||||
end
|
||||
|
||||
if intent&.status == 'succeeded'
|
||||
if params[:cart_items][:reservation]
|
||||
res = on_reservation_success(intent, amount[:details])
|
||||
elsif params[:cart_items][:subscription]
|
||||
res = on_subscription_success(intent, amount[:details])
|
||||
if cart.reservation
|
||||
res = on_reservation_success(intent, amount[:details], cart)
|
||||
elsif cart.subscription
|
||||
res = on_subscription_success(intent, amount[:details], cart)
|
||||
end
|
||||
end
|
||||
|
||||
@ -79,12 +80,13 @@ class API::StripeController < API::PaymentsController
|
||||
key = Setting.get('stripe_secret_key')
|
||||
intent = Stripe::SetupIntent.retrieve(params[:setup_intent_id], api_key: key)
|
||||
|
||||
amount = card_amount
|
||||
cart = shopping_cart
|
||||
amount = debit_amount(cart)
|
||||
if intent&.status == 'succeeded'
|
||||
if params[:cart_items][:reservation]
|
||||
res = on_reservation_success(intent, amount[:details])
|
||||
elsif params[:cart_items][:subscription]
|
||||
res = on_subscription_success(intent, amount[:details])
|
||||
if cart.reservation
|
||||
res = on_reservation_success(intent, amount[:details], cart)
|
||||
elsif cart.subscription
|
||||
res = on_subscription_success(intent, amount[:details], cart)
|
||||
end
|
||||
end
|
||||
|
||||
@ -126,12 +128,12 @@ class API::StripeController < API::PaymentsController
|
||||
)
|
||||
end
|
||||
|
||||
def on_reservation_success(intent, details)
|
||||
super(intent.id, intent.class.name, details)
|
||||
def on_reservation_success(intent, details, cart)
|
||||
super(intent.id, intent.class.name, details, cart)
|
||||
end
|
||||
|
||||
def on_subscription_success(intent, details)
|
||||
super(intent.id, intent.class.name, details)
|
||||
def on_subscription_success(intent, details, cart)
|
||||
super(intent.id, intent.class.name, details, cart)
|
||||
end
|
||||
|
||||
def generate_payment_response(intent, res = nil)
|
||||
|
@ -9,28 +9,6 @@ class API::SubscriptionsController < API::ApiController
|
||||
authorize @subscription
|
||||
end
|
||||
|
||||
# Admins can create any subscriptions. Members can directly create subscriptions if total = 0,
|
||||
# otherwise, they must use payments_controller#confirm_payment.
|
||||
# Managers can create subscriptions for other users
|
||||
def create
|
||||
user_id = current_user.admin? || current_user.manager? ? params[:customer_id] : current_user.id
|
||||
transaction = transaction_amount(user_id)
|
||||
|
||||
authorize SubscriptionContext.new(Subscription, transaction[:amount], user_id)
|
||||
|
||||
@subscription = Subscription.new(subscription_params)
|
||||
is_subscribe = Subscriptions::Subscribe.new(current_user.invoicing_profile.id, user_id)
|
||||
.pay_and_save(@subscription, payment_details: transaction[:details],
|
||||
schedule: params[:subscription][:payment_schedule],
|
||||
payment_method: params[:subscription][:payment_method])
|
||||
|
||||
if is_subscribe
|
||||
render :show, status: :created, location: @subscription
|
||||
else
|
||||
render json: @subscription.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
authorize @subscription
|
||||
|
||||
@ -50,42 +28,11 @@ class API::SubscriptionsController < API::ApiController
|
||||
|
||||
private
|
||||
|
||||
def transaction_amount(user_id)
|
||||
cs = CartService.new(current_user)
|
||||
cart = cs.from_hash(customer_id: user_id,
|
||||
subscription: {
|
||||
plan_id: subscription_params[:plan_id]
|
||||
},
|
||||
coupon_code: coupon_params[:coupon_code],
|
||||
payment_schedule: params[:payment_schedule])
|
||||
price_details = cart.total
|
||||
user = User.find(user_id)
|
||||
|
||||
# Subtract wallet amount from total
|
||||
total = price_details[:total]
|
||||
wallet_debit = get_wallet_debit(user, total)
|
||||
{ amount: total - wallet_debit, details: price_details }
|
||||
end
|
||||
|
||||
def get_wallet_debit(user, total_amount)
|
||||
wallet_amount = (user.wallet.amount * 100).to_i
|
||||
wallet_amount >= total_amount ? total_amount : wallet_amount
|
||||
end
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_subscription
|
||||
@subscription = Subscription.find(params[:id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def subscription_params
|
||||
params.require(:subscription).permit(:plan_id)
|
||||
end
|
||||
|
||||
def coupon_params
|
||||
params.permit(:coupon_code)
|
||||
end
|
||||
|
||||
def subscription_update_params
|
||||
params.require(:subscription).permit(:expired_at)
|
||||
end
|
||||
|
@ -657,12 +657,12 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
* @param reservation {Object} as returned by mkReservation()
|
||||
* @param coupon {Object} Coupon as returned from the API
|
||||
* @param paymentMethod {string} 'card' | ''
|
||||
* @return {{reservation:Object, coupon_code:string}}
|
||||
* @return {CartItems}
|
||||
*/
|
||||
const mkCartItems = function (reservation, coupon, paymentMethod = '') {
|
||||
return {
|
||||
customer_id: $scope.ctrl.member.id,
|
||||
reservation,
|
||||
items: [reservation],
|
||||
coupon_code: ((coupon ? coupon.code : undefined)),
|
||||
payment_method: paymentMethod,
|
||||
};
|
||||
@ -733,8 +733,8 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
return mkCartItems(reservation, $scope.coupon.applied);
|
||||
},
|
||||
},
|
||||
controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'Auth', 'Reservation', 'wallet', 'helpers', '$filter', 'coupon', 'cartItems',
|
||||
function ($scope, $uibModalInstance, $state, reservation, price, Auth, Reservation, wallet, helpers, $filter, coupon, cartItems) {
|
||||
controller: ['$scope', '$uibModalInstance', '$state', 'reservation', 'price', 'Auth', 'LocalPayment', 'wallet', 'helpers', '$filter', 'coupon', 'cartItems',
|
||||
function ($scope, $uibModalInstance, $state, reservation, price, Auth, LocalPayment, wallet, helpers, $filter, coupon, cartItems) {
|
||||
// User's wallet amount
|
||||
$scope.wallet = wallet;
|
||||
|
||||
@ -767,7 +767,7 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
// Callback to validate the payment
|
||||
$scope.ok = function () {
|
||||
$scope.attempting = true;
|
||||
return Reservation.save(mkCartItems($scope.reservation, coupon), function (reservation) {
|
||||
return LocalPayment.confirm(cartItems, function (reservation) {
|
||||
$uibModalInstance.close(reservation);
|
||||
return $scope.attempting = true;
|
||||
}
|
||||
|
@ -687,16 +687,13 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
|
||||
* @return {CartItems}
|
||||
*/
|
||||
const mkCartItems = function (items, paymentMethod = '') {
|
||||
const cartItems = {
|
||||
return {
|
||||
customer_id: $scope.user.id,
|
||||
items,
|
||||
payment_schedule: $scope.schedule.requested_schedule,
|
||||
payment_method: paymentMethod,
|
||||
coupon_code: (($scope.coupon.applied ? $scope.coupon.applied.code : undefined))
|
||||
};
|
||||
for (const item of items) {
|
||||
Object.assign(cartItems, item);
|
||||
}
|
||||
return cartItems;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -745,8 +742,8 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
|
||||
return $scope.settings;
|
||||
}
|
||||
},
|
||||
controller: ['$scope', '$uibModalInstance', '$state', 'price', 'Auth', 'Reservation', 'Subscription', 'wallet', 'helpers', '$filter', 'coupon', 'selectedPlan', 'schedule', 'cartItems', 'user', 'settings',
|
||||
function ($scope, $uibModalInstance, $state, price, Auth, Reservation, Subscription, wallet, helpers, $filter, coupon, selectedPlan, schedule, cartItems, user, settings) {
|
||||
controller: ['$scope', '$uibModalInstance', '$state', 'price', 'Auth', 'LocalPayment', 'wallet', 'helpers', '$filter', 'coupon', 'selectedPlan', 'schedule', 'cartItems', 'user', 'settings',
|
||||
function ($scope, $uibModalInstance, $state, price, Auth, LocalPayment, wallet, helpers, $filter, coupon, selectedPlan, schedule, cartItems, user, settings) {
|
||||
// user wallet amount
|
||||
$scope.wallet = wallet;
|
||||
|
||||
@ -783,6 +780,30 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
|
||||
// the customer
|
||||
$scope.user = user;
|
||||
|
||||
/**
|
||||
* Check if the shopping cart contains a reservation
|
||||
* @return {Reservation|boolean}
|
||||
*/
|
||||
$scope.reservation = (function () {
|
||||
const item = cartItems.items.find(i => i.reservation);
|
||||
if (item && item.reservation.slots_attributes.length > 0) {
|
||||
return item.reservation;
|
||||
}
|
||||
return false;
|
||||
})();
|
||||
|
||||
/**
|
||||
* Check if the shopping cart contains a subscription
|
||||
* @return {Subscription|boolean}
|
||||
*/
|
||||
$scope.subscription = (function () {
|
||||
const item = cartItems.items.find(i => i.subscription);
|
||||
if (item && item.subscription.plan_id) {
|
||||
return item.subscription;
|
||||
}
|
||||
return false;
|
||||
})();
|
||||
|
||||
/**
|
||||
* Callback to process the local payment, triggered on button click
|
||||
*/
|
||||
@ -796,22 +817,7 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
|
||||
}
|
||||
}
|
||||
$scope.attempting = true;
|
||||
// save subscription (if there's only a subscription selected)
|
||||
if ((!$scope.cartItems.reservation || $scope.cartItems.reservation.slots_attributes.length === 0) && selectedPlan) {
|
||||
const sub = mkSubscription(selectedPlan.id);
|
||||
|
||||
return Subscription.save(mkCartItems([sub], $scope.method.payment_method),
|
||||
function (subscription) {
|
||||
$uibModalInstance.close(subscription);
|
||||
$scope.attempting = true;
|
||||
}, function (response) {
|
||||
$scope.alerts = [];
|
||||
$scope.alerts.push({ msg: _t('app.shared.cart.a_problem_occurred_during_the_payment_process_please_try_again_later'), type: 'danger' });
|
||||
$scope.attempting = false;
|
||||
});
|
||||
}
|
||||
// otherwise, save the reservation (may include a subscription)
|
||||
Reservation.save(cartItems, function (reservation) {
|
||||
LocalPayment.confirm(cartItems, function (reservation) {
|
||||
$uibModalInstance.close(reservation);
|
||||
$scope.attempting = true;
|
||||
}, function (response) {
|
||||
|
@ -21,8 +21,7 @@ export enum PaymentMethod {
|
||||
|
||||
export interface CartItems {
|
||||
customer_id: number,
|
||||
reservation?: Reservation,
|
||||
subscription?: SubscriptionRequest,
|
||||
items: Array<Reservation|SubscriptionRequest>,
|
||||
coupon_code?: string,
|
||||
payment_schedule?: boolean,
|
||||
payment_method: PaymentMethod
|
||||
|
13
app/frontend/src/javascript/services/local_payment.js
Normal file
13
app/frontend/src/javascript/services/local_payment.js
Normal file
@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
Application.Services.factory('LocalPayment', ['$resource', function ($resource) {
|
||||
return $resource('/api/local_payment',
|
||||
{}, {
|
||||
confirm: {
|
||||
method: 'POST',
|
||||
url: '/api/local_payment/confirm_payment',
|
||||
isArray: false
|
||||
}
|
||||
}
|
||||
);
|
||||
}]);
|
@ -58,12 +58,12 @@
|
||||
<iframe name="export-frame" height="0" width="0" class="none"></iframe>
|
||||
</div>
|
||||
|
||||
<div class="widget panel b-a m m-t-lg" ng-if="availability" ng-hide="availability.available_type == 'event'">
|
||||
<div class="widget panel b-a m m-t-lg" ng-if="availability" ng-show="(availability.slot_duration || availability.tags.length > 0) && availability.available_type !== 'event'">
|
||||
<div class="panel-heading b-b small">
|
||||
<h3><i class="fa fa-info-circle m-r" aria-hidden="true"></i><span translate>{{ 'app.admin.calendar.info' }}</span></h3>
|
||||
</div>
|
||||
<div class="widget-content no-bg auto wrapper">
|
||||
<div translate translate-values="{DURATION: availability.slot_duration}">{{ 'app.admin.calendar.slot_duration' }}</div>
|
||||
<div translate translate-values="{DURATION: availability.slot_duration}" ng-show="availability.slot_duration">{{ 'app.admin.calendar.slot_duration' }}</div>
|
||||
<div class="m-t-sm" ng-show="availability.tags.length > 0">
|
||||
<span translate>{{ 'app.admin.calendar.tags' }}</span>
|
||||
<ul>
|
||||
|
@ -1,19 +1,19 @@
|
||||
<div class="modal-header">
|
||||
<img ng-src="{{logoBlack.custom_asset_file_attributes.attachment_url}}" alt="{{logo.custom_asset_file_attributes.attachment}}" class="modal-logo"/>
|
||||
<h1 translate ng-show="cartItems.reservation">{{ 'app.shared.valid_reservation_modal.booking_confirmation' }}</h1>
|
||||
<h1 translate ng-show="!cartItems.reservation && cartItems.subscription">{{ 'app.shared.valid_reservation_modal.subscription_confirmation' }}</h1>
|
||||
<h1 translate ng-show="reservation">{{ 'app.shared.valid_reservation_modal.booking_confirmation' }}</h1>
|
||||
<h1 translate ng-show="!reservation && subscription">{{ 'app.shared.valid_reservation_modal.subscription_confirmation' }}</h1>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</uib-alert>
|
||||
<div class="row">
|
||||
<div ng-class="{'col-md-6': schedule, 'm-h-sm': !schedule}">
|
||||
<div ng-if="cartItems.reservation.slots_attributes.length > 0">
|
||||
<div ng-if="reservation">
|
||||
<p translate>{{ 'app.shared.valid_reservation_modal.here_is_the_summary_of_the_slots_to_book_for_the_current_user' }}</p>
|
||||
<ul ng-repeat="slot in cartItems.reservation.slots_attributes">
|
||||
<ul ng-repeat="slot in reservation.slots_attributes">
|
||||
<li><strong>{{slot.start_at | amDateFormat: 'LL'}} : {{slot.start_at | amDateFormat:'LT'}} - {{slot.end_at | amDateFormat:'LT'}}</strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div ng-if="cartItems.subscription">
|
||||
<div ng-if="subscription">
|
||||
<p translate>{{ 'app.shared.valid_reservation_modal.here_is_the_subscription_summary' }}</p>
|
||||
<p>{{ plan | humanReadablePlanName }}</p>
|
||||
</div>
|
||||
|
@ -34,7 +34,23 @@ class CartItem::EventReservation < CartItem::Reservation
|
||||
{ elements: elements, amount: total }
|
||||
end
|
||||
|
||||
def to_reservation
|
||||
::Reservation.new(
|
||||
reservable_id: @reservable.id,
|
||||
reservable_type: Event.name,
|
||||
slots_attributes: slots_params,
|
||||
tickets_attributes: tickets_params,
|
||||
nb_reserve_places: @normal_tickets
|
||||
)
|
||||
end
|
||||
|
||||
def name
|
||||
@reservable.title
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def tickets_params
|
||||
@other_tickets.map { |ticket| ticket.permit(:event_price_category_id, :booked) }
|
||||
end
|
||||
end
|
||||
|
@ -12,6 +12,14 @@ class CartItem::MachineReservation < CartItem::Reservation
|
||||
@new_subscription = new_subscription
|
||||
end
|
||||
|
||||
def to_reservation
|
||||
::Reservation.new(
|
||||
reservable_id: @reservable.id,
|
||||
reservable_type: Machine.name,
|
||||
slots_attributes: slots_params
|
||||
)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def credits
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
# A payment schedule applied to plan in the shopping cart
|
||||
class CartItem::PaymentSchedule
|
||||
attr_reader :requested
|
||||
|
||||
def initialize(plan, coupon, requested)
|
||||
raise TypeError unless coupon.is_a? CartItem::Coupon
|
||||
|
||||
|
@ -33,6 +33,10 @@ class CartItem::Reservation < CartItem::BaseItem
|
||||
@reservable.name
|
||||
end
|
||||
|
||||
def to_reservation
|
||||
nil
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def credits
|
||||
@ -84,4 +88,8 @@ class CartItem::Reservation < CartItem::BaseItem
|
||||
end
|
||||
hours_available
|
||||
end
|
||||
|
||||
def slots_params
|
||||
@slots.map { |slot| slot.permit(:id, :start_at, :end_at, :availability_id, :offered) }
|
||||
end
|
||||
end
|
||||
|
@ -12,6 +12,14 @@ class CartItem::SpaceReservation < CartItem::Reservation
|
||||
@new_subscription = new_subscription
|
||||
end
|
||||
|
||||
def to_reservation
|
||||
::Reservation.new(
|
||||
reservable_id: @reservable.id,
|
||||
reservable_type: Space.name,
|
||||
slots_attributes: slots_params
|
||||
)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def credits
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
# A subscription added to the shopping cart
|
||||
class CartItem::Subscription < CartItem::BaseItem
|
||||
attr_reader :plan
|
||||
|
||||
def initialize(plan)
|
||||
raise TypeError unless plan.is_a? Plan
|
||||
|
||||
@ -18,4 +20,10 @@ class CartItem::Subscription < CartItem::BaseItem
|
||||
def name
|
||||
@plan.name
|
||||
end
|
||||
|
||||
def to_subscription
|
||||
Subscription.new(
|
||||
plan_id: @plan.id
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -32,6 +32,14 @@ class CartItem::TrainingReservation < CartItem::Reservation
|
||||
{ elements: elements, amount: amount }
|
||||
end
|
||||
|
||||
def to_reservation
|
||||
::Reservation.new(
|
||||
reservable_id: @reservable.id,
|
||||
reservable_type: Training.name,
|
||||
slots_attributes: slots_params
|
||||
)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def credits
|
||||
|
@ -80,6 +80,6 @@ class Machine < ApplicationRecord
|
||||
private
|
||||
|
||||
def update_gateway_product
|
||||
PaymentGatewayService.create_or_update_product(Machine.name, id)
|
||||
PaymentGatewayService.new.create_or_update_product(Machine.name, id)
|
||||
end
|
||||
end
|
||||
|
@ -131,6 +131,6 @@ class Plan < ApplicationRecord
|
||||
end
|
||||
|
||||
def update_gateway_product
|
||||
PaymentGatewayService.create_or_update_product(Plan.name, id)
|
||||
PaymentGatewayService.new.create_or_update_product(Plan.name, id)
|
||||
end
|
||||
end
|
||||
|
@ -18,6 +18,14 @@ class ShoppingCart
|
||||
@payment_schedule = payment_schedule
|
||||
end
|
||||
|
||||
def subscription
|
||||
@items.find { |item| item.is_a? CartItem::Subscription }
|
||||
end
|
||||
|
||||
def reservation
|
||||
@items.find { |item| item.is_a? CartItem::Reservation }
|
||||
end
|
||||
|
||||
# compute the price details of the current shopping cart
|
||||
def total
|
||||
total_amount = 0
|
||||
|
@ -68,6 +68,6 @@ class Space < ApplicationRecord
|
||||
private
|
||||
|
||||
def update_gateway_product
|
||||
PaymentGatewayService.create_or_update_product(Space.name, id)
|
||||
PaymentGatewayService.new.create_or_update_product(Space.name, id)
|
||||
end
|
||||
end
|
||||
|
@ -70,6 +70,6 @@ class Training < ApplicationRecord
|
||||
end
|
||||
|
||||
def update_gateway_product
|
||||
PaymentGatewayService.create_or_update_product(Training.name, id)
|
||||
PaymentGatewayService.new.create_or_update_product(Training.name, id)
|
||||
end
|
||||
end
|
||||
|
15
app/policies/local_payment_context.rb
Normal file
15
app/policies/local_payment_context.rb
Normal file
@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Pundit Additional context to validate the price of a local payment
|
||||
class LocalPaymentContext
|
||||
attr_reader :shopping_cart, :price
|
||||
|
||||
def initialize(shopping_cart, price)
|
||||
@shopping_cart = shopping_cart
|
||||
@price = price
|
||||
end
|
||||
|
||||
def policy_class
|
||||
LocalPaymentPolicy
|
||||
end
|
||||
end
|
8
app/policies/local_payment_policy.rb
Normal file
8
app/policies/local_payment_policy.rb
Normal file
@ -0,0 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Check the access policies for API::LocalPaymentsController
|
||||
class LocalPaymentPolicy < ApplicationPolicy
|
||||
def confirm_payment?
|
||||
user.admin? || (user.manager? && record.shopping_cart.customer.id != user.id) || record.price.zero?
|
||||
end
|
||||
end
|
@ -15,8 +15,13 @@ class CartService
|
||||
plan_info = plan(cart_items)
|
||||
|
||||
items = []
|
||||
items.push(CartItem::Subscription.new(plan_info[:plan])) if plan_info[:new_subscription]
|
||||
items.push(reservable_from_hash(cart_items[:reservation], plan_info)) if cart_items[:reservation]
|
||||
cart_items[:items].each do |item|
|
||||
if item.keys.first == 'subscription'
|
||||
items.push(CartItem::Subscription.new(plan_info[:plan])) if plan_info[:new_subscription]
|
||||
elsif item.keys.first == 'reservation'
|
||||
items.push(reservable_from_hash(item[:reservation], plan_info))
|
||||
end
|
||||
end
|
||||
|
||||
coupon = CartItem::Coupon.new(@customer, @operator, cart_items[:coupon_code])
|
||||
schedule = CartItem::PaymentSchedule.new(plan_info[:plan], coupon, cart_items[:payment_schedule])
|
||||
@ -33,14 +38,16 @@ class CartService
|
||||
private
|
||||
|
||||
def plan(cart_items)
|
||||
plan = if cart_items[:subscription] && cart_items[:subscription][:plan_id]
|
||||
new_plan_being_bought = true
|
||||
Plan.find(cart_items[:subscription][:plan_id])
|
||||
new_plan_being_bought = false
|
||||
plan = if cart_items[:items].any? { |item| item.keys.first == 'subscription' }
|
||||
index = cart_items[:items].index { |item| item.keys.first == 'subscription' }
|
||||
if cart_items[:items][index][:subscription][:plan_id]
|
||||
new_plan_being_bought = true
|
||||
Plan.find(cart_items[:items][index][:subscription][:plan_id])
|
||||
end
|
||||
elsif @customer.subscribed_plan
|
||||
new_plan_being_bought = false
|
||||
@customer.subscribed_plan
|
||||
else
|
||||
new_plan_being_bought = false
|
||||
nil
|
||||
end
|
||||
{ plan: plan, new_subscription: new_plan_being_bought }
|
||||
|
@ -3,16 +3,17 @@
|
||||
# create remote items on currently active payment gateway
|
||||
class PaymentGatewayService
|
||||
def initialize
|
||||
@gateway = if Stripe::Helper.enabled?
|
||||
require 'stripe/service'
|
||||
Stripe::Service
|
||||
elsif PayZen::Helper.enabled?
|
||||
require 'pay_zen/service'
|
||||
PayZen::Service
|
||||
else
|
||||
require 'payment/service'
|
||||
Payment::Service
|
||||
end
|
||||
service = if Stripe::Helper.enabled?
|
||||
require 'stripe/service'
|
||||
Stripe::Service
|
||||
elsif PayZen::Helper.enabled?
|
||||
require 'pay_zen/service'
|
||||
PayZen::Service
|
||||
else
|
||||
require 'payment/service'
|
||||
Payment::Service
|
||||
end
|
||||
@gateway = service.new
|
||||
end
|
||||
|
||||
def create_subscription(payment_schedule, gateway_object_id)
|
||||
|
@ -65,9 +65,13 @@ class Subscriptions::Subscribe
|
||||
operator = InvoicingProfile.find(@operator_profile_id).user
|
||||
cs = CartService.new(operator)
|
||||
cart = cs.from_hash(customer_id: subscription.user.id,
|
||||
subscription: {
|
||||
plan_id: subscription.plan_id
|
||||
},
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: subscription.plan_id
|
||||
}
|
||||
}
|
||||
],
|
||||
payment_schedule: !schedule.nil?)
|
||||
details = cart.total
|
||||
|
||||
|
@ -57,7 +57,7 @@ Rails.application.routes.draw do
|
||||
patch ':id/complete_tour', action: 'complete_tour', on: :collection
|
||||
patch ':id/update_role', action: 'update_role', on: :collection
|
||||
end
|
||||
resources :reservations, only: %i[show create index update]
|
||||
resources :reservations, only: %i[show index update]
|
||||
resources :notifications, only: %i[index show update] do
|
||||
match :update_all, path: '/', via: %i[put patch], on: :collection
|
||||
get 'polling', action: 'polling', on: :collection
|
||||
@ -95,7 +95,7 @@ Rails.application.routes.draw do
|
||||
end
|
||||
|
||||
resources :groups, only: %i[index create update destroy]
|
||||
resources :subscriptions, only: %i[show create update]
|
||||
resources :subscriptions, only: %i[show update]
|
||||
resources :plans, only: %i[index create update destroy show]
|
||||
resources :slots, only: [:update] do
|
||||
put 'cancel', on: :member
|
||||
@ -186,6 +186,9 @@ Rails.application.routes.draw do
|
||||
post 'payzen/check_hash' => 'payzen#check_hash'
|
||||
post 'payzen/create_token' => 'payzen#create_token'
|
||||
|
||||
# local payments handling
|
||||
post 'local_payment/confirm_payment' => 'local_payment#confirm_payment'
|
||||
|
||||
# FabAnalytics
|
||||
get 'analytics/data' => 'analytics#data'
|
||||
|
||||
|
@ -155,7 +155,7 @@ This procedure is not easy to follow so if you don't need to write some code for
|
||||
<a name="tests"></a>
|
||||
## Tests
|
||||
|
||||
Run the test suite with `./scripts/run-tests.sh`.
|
||||
Run the test suite with `./scripts/tests.sh`.
|
||||
|
||||
Pleas note: If you haven't set the Stripe's API keys in your `.env` file, the script will ask for them.
|
||||
You must provide valid Stripe API **test keys** for the test suite to run.
|
||||
|
@ -25,7 +25,7 @@ This document is listing common known issues.
|
||||
To solve this issue copy `env.example` to `.env`.
|
||||
This is required before the first start.
|
||||
|
||||
- When running the tests suite with `scripts/run-tests.sh`, all tests may fail with errors similar to the following:
|
||||
- When running the tests suite with `scripts/tests.sh`, all tests may fail with errors similar to the following:
|
||||
|
||||
Error:
|
||||
...
|
||||
|
@ -55,7 +55,7 @@ docker-compose up -d
|
||||
|
||||
- Install and configure the PostgreSQL extension [pgextwlist](https://github.com/dimitri/pgextwlist).
|
||||
Please follow the instructions detailed on the extension website to whitelist `unaccent` and `trigram` for the user configured in `config/database.yml`.
|
||||
- If you intend to contribute to the project code, you will need to run the test suite with `scripts/run-tests.sh`.
|
||||
- If you intend to contribute to the project code, you will need to run the test suite with `scripts/tests.sh`.
|
||||
This also requires your user to have the _SUPERUSER_ role.
|
||||
Please see the [known issues](known-issues.md) documentation for more information about this.
|
||||
|
||||
|
2
test/fixtures/invoices.yml
vendored
2
test/fixtures/invoices.yml
vendored
@ -9,7 +9,7 @@ invoice_1:
|
||||
invoicing_profile_id: 3
|
||||
statistic_profile_id: 3
|
||||
reference: 1604001/VL
|
||||
payment_method:
|
||||
payment_method: card
|
||||
avoir_date:
|
||||
invoice_id:
|
||||
type:
|
||||
|
@ -62,22 +62,26 @@ module Events
|
||||
assert_equal 10, e.nb_free_places, 'Number of free places was not updated'
|
||||
|
||||
# Now, let's make a reservation on this event
|
||||
post '/api/reservations',
|
||||
post '/api/local_payment/confirm_payment',
|
||||
params: {
|
||||
customer_id: User.find_by(username: 'pdurand').id,
|
||||
reservation: {
|
||||
reservable_id: e.id,
|
||||
reservable_type: 'Event',
|
||||
nb_reserve_places: 2,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: e.availability.start_at,
|
||||
end_at: e.availability.end_at,
|
||||
availability_id: e.availability.id,
|
||||
offered: false
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: e.id,
|
||||
reservable_type: 'Event',
|
||||
nb_reserve_places: 2,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: e.availability.start_at,
|
||||
end_at: e.availability.end_at,
|
||||
availability_id: e.availability.id,
|
||||
offered: false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json,
|
||||
headers: default_headers
|
||||
|
||||
@ -156,28 +160,32 @@ module Events
|
||||
assert_equal 10, e.nb_free_places, 'Number of free places was not updated'
|
||||
|
||||
# Now, let's make a reservation on this event
|
||||
post '/api/reservations',
|
||||
post '/api/local_payment/confirm_payment',
|
||||
params: {
|
||||
customer_id: User.find_by(username: 'lseguin').id,
|
||||
reservation: {
|
||||
reservable_id: e.id,
|
||||
reservable_type: 'Event',
|
||||
nb_reserve_places: 4,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: e.availability.start_at,
|
||||
end_at: e.availability.end_at,
|
||||
availability_id: e.availability.id,
|
||||
offered: false
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: e.id,
|
||||
reservable_type: 'Event',
|
||||
nb_reserve_places: 4,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: e.availability.start_at,
|
||||
end_at: e.availability.end_at,
|
||||
availability_id: e.availability.id,
|
||||
offered: false
|
||||
}
|
||||
],
|
||||
tickets_attributes: [
|
||||
{
|
||||
event_price_category_id: e.event_price_categories.first.id,
|
||||
booked: 4
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
tickets_attributes: [
|
||||
{
|
||||
event_price_category_id: e.event_price_categories.first.id,
|
||||
booked: 4
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json,
|
||||
headers: default_headers
|
||||
|
||||
|
@ -34,29 +34,33 @@ class Events::AsUserTest < ActionDispatch::IntegrationTest
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
customer_id: User.find_by(username: 'vlonchamp').id,
|
||||
reservation: {
|
||||
reservable_id: radio.id,
|
||||
reservable_type: 'Event',
|
||||
nb_reserve_places: 2,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at,
|
||||
end_at: availability.end_at,
|
||||
availability_id: availability.id,
|
||||
offered: false
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: radio.id,
|
||||
reservable_type: 'Event',
|
||||
nb_reserve_places: 2,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at,
|
||||
end_at: availability.end_at,
|
||||
availability_id: availability.id,
|
||||
offered: false
|
||||
}
|
||||
],
|
||||
tickets_attributes: [
|
||||
{
|
||||
event_price_category_id: radio.event_price_categories[0].id,
|
||||
booked: 2
|
||||
},
|
||||
{
|
||||
event_price_category_id: radio.event_price_categories[1].id,
|
||||
booked: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
tickets_attributes: [
|
||||
{
|
||||
event_price_category_id: radio.event_price_categories[0].id,
|
||||
booked: 2
|
||||
},
|
||||
{
|
||||
event_price_category_id: radio.event_price_categories[1].id,
|
||||
booked: 2
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
],
|
||||
coupon_code: 'SUNNYFABLAB'
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
|
@ -15,18 +15,22 @@ module Prices
|
||||
post '/api/prices/compute',
|
||||
params: {
|
||||
customer_id: user.id,
|
||||
reservation: {
|
||||
reservable_id: printer_training.id,
|
||||
reservable_type: printer_training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
availability_id: availability.id,
|
||||
end_at: availability.end_at,
|
||||
offered: false,
|
||||
start_at: availability.start_at
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: printer_training.id,
|
||||
reservable_type: printer_training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
availability_id: availability.id,
|
||||
end_at: availability.end_at,
|
||||
offered: false,
|
||||
start_at: availability.start_at
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json,
|
||||
headers: default_headers
|
||||
|
||||
@ -50,27 +54,33 @@ module Prices
|
||||
post '/api/prices/compute',
|
||||
params: {
|
||||
customer_id: user.id,
|
||||
reservation: {
|
||||
reservable_id: laser.id,
|
||||
reservable_type: laser.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
availability_id: availability.id,
|
||||
end_at: (availability.start_at + 1.hour).strftime('%Y-%m-%d %H:%M:%S.%9N Z'),
|
||||
offered: true,
|
||||
start_at: availability.start_at.strftime('%Y-%m-%d %H:%M:%S.%9N Z')
|
||||
},
|
||||
{
|
||||
availability_id: availability.id,
|
||||
end_at: (availability.start_at + 2.hour).strftime('%Y-%m-%d %H:%M:%S.%9N Z'),
|
||||
offered: false,
|
||||
start_at: (availability.start_at + 1.hour).strftime('%Y-%m-%d %H:%M:%S.%9N Z')
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: laser.id,
|
||||
reservable_type: laser.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
availability_id: availability.id,
|
||||
end_at: (availability.start_at + 1.hour).strftime('%Y-%m-%d %H:%M:%S.%9N Z'),
|
||||
offered: true,
|
||||
start_at: availability.start_at.strftime('%Y-%m-%d %H:%M:%S.%9N Z')
|
||||
},
|
||||
{
|
||||
availability_id: availability.id,
|
||||
end_at: (availability.start_at + 2.hour).strftime('%Y-%m-%d %H:%M:%S.%9N Z'),
|
||||
offered: false,
|
||||
start_at: (availability.start_at + 1.hour).strftime('%Y-%m-%d %H:%M:%S.%9N Z')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
},
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json,
|
||||
headers: default_headers
|
||||
|
||||
|
@ -19,19 +19,23 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_items_count = InvoiceItem.count
|
||||
users_credit_count = UsersCredit.count
|
||||
|
||||
post reservations_path, params: {
|
||||
post '/api/local_payment/confirm_payment', params: {
|
||||
customer_id: @user_without_subscription.id,
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
@ -78,19 +82,21 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_count = Invoice.count
|
||||
invoice_items_count = InvoiceItem.count
|
||||
|
||||
post reservations_path, params: {
|
||||
post '/api/local_payment/confirm_payment', params: {
|
||||
customer_id: @user_without_subscription.id,
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
items: [
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
@ -137,24 +143,28 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_items_count = InvoiceItem.count
|
||||
users_credit_count = UsersCredit.count
|
||||
|
||||
post reservations_path, params: {
|
||||
post '/api/local_payment/confirm_payment', params: {
|
||||
customer_id: @user_with_subscription.id,
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
},
|
||||
{
|
||||
start_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
end_at: (availability.start_at + 2.hours).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
},
|
||||
{
|
||||
start_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
end_at: (availability.start_at + 2.hours).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
@ -212,19 +222,23 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_items_count = InvoiceItem.count
|
||||
users_credit_count = UsersCredit.count
|
||||
|
||||
post reservations_path, params: {
|
||||
post '/api/local_payment/confirm_payment', params: {
|
||||
customer_id: @vlonchamp.id,
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
@ -284,22 +298,28 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
users_credit_count = UsersCredit.count
|
||||
wallet_transactions_count = WalletTransaction.count
|
||||
|
||||
post reservations_path, params: {
|
||||
post '/api/local_payment/confirm_payment', params: {
|
||||
customer_id: @vlonchamp.id,
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
},
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
@ -355,19 +375,23 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_items_count = InvoiceItem.count
|
||||
users_credit_count = UsersCredit.count
|
||||
|
||||
post reservations_path, params: {
|
||||
post '/api/local_payment/confirm_payment', params: {
|
||||
customer_id: @vlonchamp.id,
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
@ -400,23 +424,29 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_items_count = InvoiceItem.count
|
||||
users_credit_count = UsersCredit.count
|
||||
|
||||
post reservations_path, params: {
|
||||
post '/api/local_payment/confirm_payment', params: {
|
||||
customer_id: @user_without_subscription.id,
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
offered: false,
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
offered: false,
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
}
|
||||
},
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
@ -481,24 +511,30 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
plan = Plan.find_by(group_id: @user_without_subscription.group.id, type: 'Plan', base_name: 'Abonnement mensualisable')
|
||||
|
||||
VCR.use_cassette('reservations_admin_training_subscription_with_payment_schedule') do
|
||||
post reservations_path, params: {
|
||||
post '/api/local_payment/confirm_payment', params: {
|
||||
payment_method: 'check',
|
||||
payment_schedule: true,
|
||||
customer_id: @user_without_subscription.id,
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
},
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
|
||||
|
@ -25,17 +25,21 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
@ -95,17 +99,21 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method(error: :card_declined),
|
||||
cart_items: {
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
@ -143,17 +151,21 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: availability.end_at.to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: availability.end_at.to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
@ -212,22 +224,26 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
},
|
||||
{
|
||||
start_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
end_at: (availability.start_at + 2.hours).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
},
|
||||
{
|
||||
start_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
end_at: (availability.start_at + 2.hours).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
@ -292,19 +308,23 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
invoice_items_count = InvoiceItem.count
|
||||
|
||||
VCR.use_cassette('reservations_create_for_training_with_subscription_success') do
|
||||
post '/api/reservations',
|
||||
post '/api/local_payment/confirm_payment',
|
||||
params: {
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: availability.end_at.to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: availability.end_at.to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
|
||||
@ -368,17 +388,21 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
customer_id: @vlonchamp.id,
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
@ -450,20 +474,26 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: availability.end_at.to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: availability.end_at.to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
},
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
@ -530,20 +560,26 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
},
|
||||
},
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
],
|
||||
coupon_code: 'SUNNYFABLAB'
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
@ -624,18 +660,22 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
customer_id: @user_without_subscription.id,
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
card_token: stripe_payment_method,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
card_token: stripe_payment_method,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
],
|
||||
coupon_code: 'XMAS10'
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
@ -700,20 +740,26 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
setup_intent_id: setup_intent[:id],
|
||||
cart_items: {
|
||||
payment_schedule: true,
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
}
|
||||
},
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
@ -797,20 +843,26 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
cart_items: {
|
||||
coupon_code: 'GIME3EUR',
|
||||
payment_schedule: true,
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
},
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
|
@ -13,12 +13,16 @@ class Subscriptions::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
plan = Plan.find_by(group_id: user.group.id, type: 'Plan', base_name: 'Mensuel')
|
||||
|
||||
VCR.use_cassette('subscriptions_admin_create_success') do
|
||||
post '/api/subscriptions',
|
||||
post '/api/local_payment/confirm_payment',
|
||||
params: {
|
||||
customer_id: user.id,
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
|
||||
@ -95,11 +99,15 @@ class Subscriptions::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
setup_intent_id: setup_intent[:id],
|
||||
cart_items: {
|
||||
customer_id: user.id,
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
payment_schedule: true,
|
||||
payment_method: 'stripe'
|
||||
}
|
||||
payment_schedule: true,
|
||||
payment_method: 'card',
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
|
@ -16,9 +16,13 @@ class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
@ -76,9 +80,13 @@ class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
@ -104,9 +112,13 @@ class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
@ -204,10 +216,14 @@ class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
setup_intent_id: setup_intent[:id],
|
||||
cart_items: {
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
payment_schedule: true
|
||||
}
|
||||
payment_schedule: true,
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
|
@ -13,12 +13,16 @@ class Subscriptions::RenewAsAdminTest < ActionDispatch::IntegrationTest
|
||||
plan = Plan.find_by(base_name: 'Mensuel tarif réduit')
|
||||
|
||||
VCR.use_cassette('subscriptions_admin_renew_success') do
|
||||
post '/api/subscriptions',
|
||||
post '/api/local_payment/confirm_payment',
|
||||
params: {
|
||||
customer_id: user.id,
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
|
||||
|
@ -16,9 +16,13 @@ class Subscriptions::RenewAsUserTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
@ -80,9 +84,13 @@ class Subscriptions::RenewAsUserTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method(error: :card_declined),
|
||||
cart_items: {
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
|
@ -19,7 +19,7 @@ VCR.configure do |config|
|
||||
end
|
||||
|
||||
Sidekiq::Testing.fake!
|
||||
Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(color: true)]
|
||||
Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(color: true)] unless ENV['RM_INFO']
|
||||
|
||||
class ActiveSupport::TestCase
|
||||
# Add more helper methods to be used by all tests here...
|
||||
|
Loading…
Reference in New Issue
Block a user