mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-29 18:52:22 +01:00
WIP: move backend code base to new architecture
- from stripe only to payment gateway abstract - from reservation params style to unified cart_items TODO: fix not passing tests, subscriptions/renew_as_admin_test.rb fails because InvoiceItem(9).amount = nil
This commit is contained in:
parent
94cbcd3236
commit
bc6ef8ef50
@ -55,13 +55,13 @@ class API::PaymentSchedulesController < API::ApiController
|
||||
authorize @payment_schedule_item.payment_schedule
|
||||
# FIXME
|
||||
stripe_key = Setting.get('stripe_secret_key')
|
||||
stp_invoice = Stripe::Invoice.pay(@payment_schedule_item.stp_invoice_id, {}, { api_key: stripe_key })
|
||||
stp_invoice = Stripe::Invoice.pay(@payment_schedule_item.payment_gateway_object.gateway_object_id, {}, { api_key: stripe_key })
|
||||
PaymentScheduleItemWorker.new.perform(@payment_schedule_item.id)
|
||||
|
||||
render json: { status: stp_invoice.status }, status: :ok
|
||||
rescue Stripe::StripeError => e
|
||||
stripe_key = Setting.get('stripe_secret_key')
|
||||
stp_invoice = Stripe::Invoice.retrieve(@payment_schedule_item.stp_invoice_id, api_key: stripe_key)
|
||||
stp_invoice = Stripe::Invoice.retrieve(@payment_schedule_item.payment_gateway_object.gateway_object_id, api_key: stripe_key)
|
||||
PaymentScheduleItemWorker.new.perform(@payment_schedule_item.id)
|
||||
|
||||
render json: { status: stp_invoice.status, error: e }, status: :unprocessable_entity
|
||||
|
@ -28,8 +28,8 @@ class API::ReservationsController < API::ApiController
|
||||
# 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[:reservation][:user_id] : current_user.id
|
||||
price = transaction_amount(current_user.admin? || (current_user.manager? && current_user.id != user_id), user_id)
|
||||
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)
|
||||
|
||||
@ -62,7 +62,7 @@ class API::ReservationsController < API::ApiController
|
||||
|
||||
private
|
||||
|
||||
def transaction_amount(is_admin, user_id)
|
||||
def transaction_amount(user_id)
|
||||
user = User.find(user_id)
|
||||
cs = CartService.new(current_user)
|
||||
cart = cs.from_hash(customer_id: user_id,
|
||||
@ -71,7 +71,7 @@ class API::ReservationsController < API::ApiController
|
||||
},
|
||||
reservation: reservation_params,
|
||||
coupon_code: coupon_params[:coupon_code],
|
||||
payment_schedule: !schedule.nil?)
|
||||
payment_schedule: reservation_params[:payment_schedule])
|
||||
price_details = cart.total
|
||||
|
||||
# Subtract wallet amount from total
|
||||
|
@ -30,7 +30,7 @@ class API::StripeController < API::PaymentsController
|
||||
currency: Setting.get('stripe_currency'),
|
||||
confirmation_method: 'manual',
|
||||
confirm: true,
|
||||
customer: current_user.stp_customer_id # FIXME
|
||||
customer: current_user.payment_gateway_object.gateway_object_id
|
||||
}, { api_key: Setting.get('stripe_secret_key') }
|
||||
)
|
||||
elsif params[:payment_intent_id].present?
|
||||
@ -71,7 +71,7 @@ class API::StripeController < API::PaymentsController
|
||||
def setup_intent
|
||||
user = User.find(params[:user_id])
|
||||
key = Setting.get('stripe_secret_key')
|
||||
@intent = Stripe::SetupIntent.create({ customer: user.stp_customer_id }, { api_key: key })
|
||||
@intent = Stripe::SetupIntent.create({ customer: user.payment_gateway_object.gateway_object_id }, { api_key: key })
|
||||
render json: { id: @intent.id, client_secret: @intent.client_secret }
|
||||
end
|
||||
|
||||
@ -96,7 +96,7 @@ class API::StripeController < API::PaymentsController
|
||||
def update_card
|
||||
user = User.find(params[:user_id])
|
||||
key = Setting.get('stripe_secret_key')
|
||||
Stripe::Customer.update(user.stp_customer_id,
|
||||
Stripe::Customer.update(user.payment_gateway_object.gateway_object_id,
|
||||
{ invoice_settings: { default_payment_method: params[:payment_method_id] } },
|
||||
{ api_key: key })
|
||||
render json: { updated: true }, status: :ok
|
||||
|
@ -57,7 +57,7 @@ class API::SubscriptionsController < API::ApiController
|
||||
plan_id: subscription_params[:plan_id]
|
||||
},
|
||||
coupon_code: coupon_params[:coupon_code],
|
||||
payment_schedule: !schedule.nil?)
|
||||
payment_schedule: subscription_params[:payment_schedule])
|
||||
price_details = cart.total
|
||||
user = User.find(user_id)
|
||||
|
||||
|
@ -16,7 +16,6 @@ class OpenAPI::V1::InvoicesDoc < OpenAPI::V1::BaseDoc
|
||||
description "Index of users' invoices, with optional pagination. Order by *created_at* descendant."
|
||||
param_group :pagination
|
||||
param :user_id, [Integer, Array], optional: true, desc: 'Scope the request to one or various users.'
|
||||
# FIXME
|
||||
example <<-INVOICES
|
||||
# /open_api/v1/invoices?user_id=211&page=1&per_page=3
|
||||
{
|
||||
|
@ -81,7 +81,7 @@ export const AbstractPaymentModal: React.FC<AbstractPaymentModalProps> = ({ isOp
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!cartItems) return;
|
||||
WalletAPI.getByUser(cartItems.reservation?.user_id || cartItems.subscription?.user_id).then((wallet) => {
|
||||
WalletAPI.getByUser(cartItems.customer_id).then((wallet) => {
|
||||
setWallet(wallet);
|
||||
PriceAPI.compute(cartItems).then((res) => {
|
||||
setPrice(res);
|
||||
|
@ -632,12 +632,11 @@ Application.Controllers.controller('ShowEventController', ['$scope', '$state', '
|
||||
* @return {{reservation:Object, coupon_code:string}}
|
||||
*/
|
||||
const mkRequestParams = function (reservation, coupon) {
|
||||
const params = {
|
||||
return {
|
||||
customer_id: reservation.user_id,
|
||||
reservation,
|
||||
coupon_code: ((coupon ? coupon.code : undefined))
|
||||
};
|
||||
|
||||
return params;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -680,18 +680,12 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
|
||||
/**
|
||||
* Create a hash map implementing the Subscription specs
|
||||
* @param planId {number}
|
||||
* @param userId {number}
|
||||
* @param schedule {boolean}
|
||||
* @param method {String} 'stripe' | 'payzen' | ''
|
||||
* @return {{subscription: {payment_schedule: boolean, user_id: number, plan_id: number}}}
|
||||
* @return {{subscription: {plan_id: number}}}
|
||||
*/
|
||||
const mkSubscription = function (planId, userId, schedule, method) {
|
||||
const mkSubscription = function (planId) {
|
||||
return {
|
||||
subscription: {
|
||||
plan_id: planId,
|
||||
user_id: userId,
|
||||
payment_schedule: schedule,
|
||||
payment_method: method
|
||||
plan_id: planId
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -703,11 +697,15 @@ Application.Directives.directive('cart', ['$rootScope', '$uibModal', 'dialogs',
|
||||
* @return {CartItems}
|
||||
*/
|
||||
const mkCartItems = function (reservation, paymentMethod) {
|
||||
let request = { reservation };
|
||||
const request = {
|
||||
customer_id: reservation.user_id,
|
||||
payment_schedule: $scope.schedule.requested_schedule,
|
||||
payment_method: paymentMethod
|
||||
};
|
||||
if (reservation.slots_attributes.length === 0 && reservation.plan_id) {
|
||||
request = mkSubscription($scope.selectedPlan.id, reservation.user_id, $scope.schedule.requested_schedule, paymentMethod);
|
||||
Object.assign(request, mkSubscription($scope.selectedPlan.id));
|
||||
} else {
|
||||
request.reservation.payment_method = paymentMethod;
|
||||
Object.assign(request, { reservation });
|
||||
}
|
||||
return mkRequestParams(request, $scope.coupon.applied);
|
||||
};
|
||||
|
@ -1,102 +0,0 @@
|
||||
/* global Stripe */
|
||||
|
||||
/**
|
||||
* This directive allows to extend a form with the Stripe payment input and error handling area.
|
||||
* Strong-customer authentication is supported.
|
||||
* --
|
||||
* https://stripe.com/docs/payments/payment-intents/web-manual
|
||||
*/
|
||||
Application.Directives.directive('stripeForm', ['Payment', 'growl', '_t',
|
||||
function (Payment, growl, _t) {
|
||||
return ({
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
cartItems: '=',
|
||||
onPaymentSuccess: '=',
|
||||
stripeKey: '@'
|
||||
},
|
||||
link: function ($scope, element, attributes) {
|
||||
const stripe = Stripe($scope.stripeKey);
|
||||
const elements = stripe.elements();
|
||||
|
||||
const style = {
|
||||
base: {
|
||||
color: '#32325d',
|
||||
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
|
||||
fontSmoothing: 'antialiased',
|
||||
fontSize: '16px',
|
||||
'::placeholder': {
|
||||
color: '#aab7c4'
|
||||
}
|
||||
},
|
||||
invalid: {
|
||||
color: '#fa755a',
|
||||
iconColor: '#fa755a'
|
||||
}
|
||||
};
|
||||
|
||||
const card = elements.create('card', { style, hidePostalCode: true });
|
||||
|
||||
card.addEventListener('change', function ({ error }) {
|
||||
const displayError = document.getElementById('card-errors');
|
||||
if (error) {
|
||||
displayError.textContent = error.message;
|
||||
} else {
|
||||
displayError.textContent = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Add an instance of the card Element into the `card-element` <div>.
|
||||
const form = angular.element(element);
|
||||
const cardElement = form.find('#card-element');
|
||||
card.mount(cardElement[0]);
|
||||
|
||||
form.bind('submit', function () {
|
||||
const button = form.find('button');
|
||||
button.prop('disabled', true);
|
||||
|
||||
stripe.createPaymentMethod('card', card).then(function ({ paymentMethod, error }) {
|
||||
if (error) {
|
||||
growl.error(error.message);
|
||||
button.prop('disabled', false);
|
||||
} else {
|
||||
// Send paymentMethod.id to your server (see Step 2)
|
||||
Payment.confirm({ payment_method_id: paymentMethod.id, cart_items: $scope.cartItems }, function (response) {
|
||||
// Handle server response (see Step 3)
|
||||
handleServerResponse(response, button);
|
||||
}, function (error) { handleServerResponse({ error }, button); });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function handleServerResponse (response, confirmButton) {
|
||||
if (response.error) {
|
||||
if (response.error.statusText) {
|
||||
growl.error(response.error.statusText);
|
||||
} else {
|
||||
growl.error(`${_t('app.shared.messages.payment_card_error')} ${response.error}`);
|
||||
}
|
||||
confirmButton.prop('disabled', false);
|
||||
} else if (response.requires_action) {
|
||||
// Use Stripe.js to handle required card action
|
||||
stripe.handleCardAction(
|
||||
response.payment_intent_client_secret
|
||||
).then(function (result) {
|
||||
if (result.error) {
|
||||
growl.error(result.error.message);
|
||||
confirmButton.prop('disabled', false);
|
||||
} else {
|
||||
// The card action has been handled
|
||||
// The PaymentIntent can be confirmed again on the server
|
||||
Payment.confirm({ payment_intent_id: result.paymentIntent.id, cart_items: $scope.cartItems }, function (confirmResult) {
|
||||
handleServerResponse(confirmResult, confirmButton);
|
||||
}, function (error) { handleServerResponse({ error }, confirmButton); });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$scope.onPaymentSuccess(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}]);
|
@ -5,8 +5,6 @@ module CartItem; end
|
||||
|
||||
# This is an abstract class implemented by classes that can be added to the shopping cart
|
||||
class CartItem::BaseItem
|
||||
self.abstract_class = true
|
||||
|
||||
def price
|
||||
{ elements: {}, amount: 0 }
|
||||
end
|
||||
|
@ -9,7 +9,7 @@ class CartItem::EventReservation < CartItem::Reservation
|
||||
|
||||
super(customer, operator, event, slots)
|
||||
@normal_tickets = normal_tickets
|
||||
@other_tickets = other_tickets
|
||||
@other_tickets = other_tickets || []
|
||||
end
|
||||
|
||||
def price
|
||||
|
@ -75,6 +75,8 @@ class CartItem::Reservation < CartItem::BaseItem
|
||||
# Compute the number of remaining hours in the users current credits (for machine or space)
|
||||
##
|
||||
def credits_hours(credits, new_plan_being_bought = false)
|
||||
return 0 unless credits
|
||||
|
||||
hours_available = credits.hours
|
||||
unless new_plan_being_bought
|
||||
user_credit = @customer.users_credits.find_by(credit_id: credits.id)
|
||||
|
@ -13,7 +13,7 @@ class CartItem::TrainingReservation < CartItem::Reservation
|
||||
end
|
||||
|
||||
def price
|
||||
base_amount = @reservable.amount_by_group(@customer.group_id, plan_id: @plan.try(:id)).amount
|
||||
base_amount = @reservable.amount_by_group(@customer.group_id).amount
|
||||
is_privileged = @operator.admin? || (@operator.manager? && @operator.id != @customer.id)
|
||||
|
||||
elements = { slots: [] }
|
||||
@ -25,7 +25,7 @@ class CartItem::TrainingReservation < CartItem::Reservation
|
||||
slot,
|
||||
is_privileged,
|
||||
elements: elements,
|
||||
has_credits: (@user.training_credits.size < hours_available),
|
||||
has_credits: (@customer.training_credits.size < hours_available),
|
||||
is_division: false)
|
||||
end
|
||||
|
||||
|
@ -26,6 +26,8 @@ class Machine < ApplicationRecord
|
||||
has_many :credits, as: :creditable, dependent: :destroy
|
||||
has_many :plans, through: :credits
|
||||
|
||||
has_one :payment_gateway_object, as: :item
|
||||
|
||||
|
||||
after_create :create_statistic_subtype
|
||||
after_create :create_machine_prices
|
||||
|
@ -10,6 +10,11 @@ class PaymentGatewayObject < ApplicationRecord
|
||||
belongs_to :subscription, foreign_type: 'Subscription', foreign_key: 'item_id'
|
||||
belongs_to :payment_schedule, foreign_type: 'PaymentSchedule', foreign_key: 'item_id'
|
||||
belongs_to :payment_schedule_item, foreign_type: 'PaymentScheduleItem', foreign_key: 'item_id'
|
||||
belongs_to :user, foreign_type: 'User', foreign_key: 'item_id'
|
||||
belongs_to :plan, foreign_type: 'Plan', foreign_key: 'item_id'
|
||||
belongs_to :machine, foreign_type: 'Machine', foreign_key: 'item_id'
|
||||
belongs_to :space, foreign_type: 'Space', foreign_key: 'item_id'
|
||||
belongs_to :training, foreign_type: 'Training', foreign_key: 'item_id'
|
||||
|
||||
def gateway_object
|
||||
Payment::ItemBuilder.build(gateway_object_type, gateway_object_id)
|
||||
|
@ -52,6 +52,10 @@ class PaymentSchedule < PaymentDocument
|
||||
payment_gateway_objects.map(&:gateway_object).find(&:payment_mean?)
|
||||
end
|
||||
|
||||
def gateway_subscription
|
||||
payment_gateway_objects.map(&:gateway_object).find { |item| !item.payment_mean? }
|
||||
end
|
||||
|
||||
def user
|
||||
invoicing_profile.user
|
||||
end
|
||||
|
@ -14,10 +14,9 @@ class PaymentScheduleItem < Footprintable
|
||||
|
||||
def payment_intent
|
||||
return unless payment_gateway_object
|
||||
# FIXME
|
||||
key = Setting.get('stripe_secret_key')
|
||||
stp_invoice = Stripe::Invoice.retrieve(stp_invoice_id, api_key: key)
|
||||
Stripe::PaymentIntent.retrieve(stp_invoice.payment_intent, api_key: key)
|
||||
|
||||
stp_invoice = payment_gateway_object.gateway_object.retrieve
|
||||
Stripe::PaymentIntent.retrieve(stp_invoice.payment_intent, api_key: Setting.get('stripe_secret_key'))
|
||||
end
|
||||
|
||||
def self.columns_out_of_footprint
|
||||
|
@ -12,6 +12,7 @@ class Plan < ApplicationRecord
|
||||
has_many :subscriptions
|
||||
has_one :plan_file, as: :viewable, dependent: :destroy
|
||||
has_many :prices, dependent: :destroy
|
||||
has_one :payment_gateway_object, as: :item
|
||||
|
||||
extend FriendlyId
|
||||
friendly_id :base_name, use: :slugged
|
||||
|
@ -25,7 +25,7 @@ class ShoppingCart
|
||||
|
||||
@items.map(&:price).each do |price|
|
||||
total_amount += price[:amount]
|
||||
all_elements.merge(price[:elements]) do |_key, old_val, new_val|
|
||||
all_elements = all_elements.merge(price[:elements]) do |_key, old_val, new_val|
|
||||
old_val | new_val
|
||||
end
|
||||
end
|
||||
|
@ -24,6 +24,8 @@ class Space < ApplicationRecord
|
||||
has_many :prices, as: :priceable, dependent: :destroy
|
||||
has_many :credits, as: :creditable, dependent: :destroy
|
||||
|
||||
has_one :payment_gateway_object, as: :item
|
||||
|
||||
after_create :create_statistic_subtype
|
||||
after_create :create_space_prices
|
||||
after_create :update_stripe_product
|
||||
|
@ -26,6 +26,8 @@ class Training < ApplicationRecord
|
||||
has_many :credits, as: :creditable, dependent: :destroy
|
||||
has_many :plans, through: :credits
|
||||
|
||||
has_one :payment_gateway_object, as: :item
|
||||
|
||||
after_create :create_statistic_subtype
|
||||
after_create :create_trainings_pricings
|
||||
after_create :update_stripe_product
|
||||
|
@ -45,6 +45,8 @@ class User < ApplicationRecord
|
||||
has_many :exports, dependent: :destroy
|
||||
has_many :imports, dependent: :nullify
|
||||
|
||||
has_one :payment_gateway_object, as: :item
|
||||
|
||||
# fix for create admin user
|
||||
before_save do
|
||||
email&.downcase!
|
||||
@ -177,11 +179,6 @@ class User < ApplicationRecord
|
||||
subscription.generate_and_save_invoice(operator_profile_id)
|
||||
end
|
||||
|
||||
def stripe_customer
|
||||
# FIXME
|
||||
Stripe::Customer.retrieve(stp_customer_id, api_key: Setting.get('stripe_secret_key'))
|
||||
end
|
||||
|
||||
def active_for_authentication?
|
||||
super && is_active?
|
||||
end
|
||||
@ -315,7 +312,7 @@ class User < ApplicationRecord
|
||||
blacklist = %w[id encrypted_password reset_password_token reset_password_sent_at remember_created_at
|
||||
sign_in_count current_sign_in_at last_sign_in_at current_sign_in_ip last_sign_in_ip confirmation_token
|
||||
confirmed_at confirmation_sent_at unconfirmed_email failed_attempts unlock_token locked_at created_at
|
||||
updated_at stp_customer_id slug provider auth_token merged_at]
|
||||
updated_at slug provider auth_token merged_at]
|
||||
User.columns_hash
|
||||
.map { |k, v| [k, v.type.to_s] }
|
||||
.delete_if { |col| blacklist.include?(col[0]) }
|
||||
|
@ -11,12 +11,11 @@ class CartService
|
||||
# @see app/frontend/src/javascript/models/payment.ts > interface CartItems
|
||||
##
|
||||
def from_hash(cart_items)
|
||||
items = []
|
||||
@customer = customer(cart_items)
|
||||
plan_info = plan(cart_items)
|
||||
|
||||
@customer = User.find(cart_items[:customer_id])
|
||||
|
||||
items.push(CartItem::Subscription.new(plan_info[:plan])) if cart_items[:subscription]
|
||||
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]
|
||||
|
||||
coupon = CartItem::Coupon.new(@customer, @operator, cart_items[:coupon_code])
|
||||
@ -37,7 +36,7 @@ class CartService
|
||||
plan = if @customer.subscribed_plan
|
||||
new_plan_being_bought = false
|
||||
@customer.subscribed_plan
|
||||
elsif cart_items[:subscription]
|
||||
elsif cart_items[:subscription] && cart_items[:subscription][:plan_id]
|
||||
new_plan_being_bought = true
|
||||
Plan.find(cart_items[:subscription][:plan_id])
|
||||
else
|
||||
@ -47,6 +46,14 @@ class CartService
|
||||
{ plan: plan, new_subscription: new_plan_being_bought }
|
||||
end
|
||||
|
||||
def customer(cart_items)
|
||||
if @operator.admin? || (@operator.manager? && @operator.id != cart_items[:customer_id])
|
||||
User.find(cart_items[:customer_id])
|
||||
else
|
||||
@operator
|
||||
end
|
||||
end
|
||||
|
||||
def reservable_from_hash(cart_item, plan_info)
|
||||
return nil if cart_item[:reservable_id].blank?
|
||||
|
||||
|
@ -78,12 +78,7 @@ class InvoicesService
|
||||
operator&.admin? || (operator&.manager? && operator != user) ? nil : Setting.get('payment_gateway')
|
||||
end
|
||||
|
||||
pgo = unless payment_id.nil?
|
||||
{
|
||||
gateway_object_id: payment_id,
|
||||
gateway_object_type: payment_type
|
||||
}
|
||||
end
|
||||
pgo = payment_id.nil? ? {} : { gateway_object_id: payment_id, gateway_object_type: payment_type }
|
||||
invoice = Invoice.new(
|
||||
invoiced: subscription || reservation,
|
||||
invoicing_profile: user.invoicing_profile,
|
||||
|
@ -61,10 +61,12 @@ class PaymentScheduleService
|
||||
ps.scheduled = reservation || subscription
|
||||
ps.payment_method = payment_method
|
||||
if !payment_id.nil? && !payment_type.nil?
|
||||
ps.payment_gateway_object = {
|
||||
pgo = PaymentGatewayObject.new(
|
||||
gateway_object_id: payment_id,
|
||||
gateway_object_type: payment_type
|
||||
}
|
||||
gateway_object_type: payment_type,
|
||||
item: ps
|
||||
)
|
||||
ps.payment_gateway_objects.push(pgo)
|
||||
end
|
||||
ps.operator_profile = operator.invoicing_profile
|
||||
ps.invoicing_profile = user.invoicing_profile
|
||||
|
@ -12,7 +12,7 @@ class StripeService
|
||||
case payment_schedule.scheduled_type
|
||||
when Reservation.name
|
||||
subscription = payment_schedule.scheduled.subscription
|
||||
reservable_stp_id = payment_schedule.scheduled.reservable&.stp_product_id
|
||||
reservable_stp_id = payment_schedule.scheduled.reservable&.payment_gateway_object&.gateway_object_id
|
||||
when Subscription.name
|
||||
subscription = payment_schedule.scheduled
|
||||
reservable_stp_id = nil
|
||||
@ -26,13 +26,13 @@ class StripeService
|
||||
intent = Stripe::SetupIntent.retrieve(setup_intent_id, api_key: stripe_key)
|
||||
# subscription (recurring price)
|
||||
price = create_price(first_item.details['recurring'],
|
||||
subscription.plan.stp_product_id,
|
||||
subscription.plan.payment_gateway_object.gateway_object_id,
|
||||
nil, monthly: true)
|
||||
# other items (not recurring)
|
||||
items = subscription_invoice_items(payment_schedule, subscription, first_item, reservable_stp_id)
|
||||
|
||||
stp_subscription = Stripe::Subscription.create({
|
||||
customer: payment_schedule.invoicing_profile.user.stp_customer_id,
|
||||
customer: payment_schedule.invoicing_profile.user.payment_gateway_object.gateway_object_id,
|
||||
cancel_at: (payment_schedule.ordered_items.last.due_date + 3.day).to_i,
|
||||
add_invoice_items: items,
|
||||
coupon: payment_schedule.coupon&.code,
|
||||
@ -41,7 +41,9 @@ class StripeService
|
||||
],
|
||||
default_payment_method: intent[:payment_method]
|
||||
}, { api_key: stripe_key })
|
||||
payment_schedule.update_attributes(stp_subscription_id: stp_subscription.id)
|
||||
pgo = PaymentGatewayObject.new(item: payment_schedule)
|
||||
pgo.gateway_object = stp_subscription
|
||||
pgo.save!
|
||||
end
|
||||
|
||||
def create_stripe_coupon(coupon_id)
|
||||
@ -72,7 +74,7 @@ class StripeService
|
||||
# adjustment: when dividing the price of the plan / months, sometimes it forces us to round the amount per month.
|
||||
# The difference is invoiced here
|
||||
p1 = create_price(first_item.details['adjustment'],
|
||||
subscription.plan.stp_product_id,
|
||||
subscription.plan.payment_gateway_object.gateway_object_id,
|
||||
"Price adjustment for payment schedule #{payment_schedule.id}")
|
||||
items.push(price: p1[:id])
|
||||
end
|
||||
@ -104,7 +106,7 @@ class StripeService
|
||||
def handle_wallet_transaction(payment_schedule)
|
||||
return unless payment_schedule.wallet_amount
|
||||
|
||||
customer_id = payment_schedule.invoicing_profile.user.stp_customer_id
|
||||
customer_id = payment_schedule.invoicing_profile.user.payment_gateway_object.gateway_object_id
|
||||
Stripe::Customer.update(customer_id, { balance: -payment_schedule.wallet_amount }, { api_key: Setting.get('stripe_secret_key') })
|
||||
end
|
||||
end
|
||||
|
@ -62,8 +62,9 @@ class Subscriptions::Subscribe
|
||||
if new_sub.save
|
||||
schedule = subscription.original_payment_schedule
|
||||
|
||||
cs = CartService.new(current_user)
|
||||
cart = cs.from_hash(customer_id: @user_id,
|
||||
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
|
||||
},
|
||||
@ -84,7 +85,7 @@ class Subscriptions::Subscribe
|
||||
details)
|
||||
end
|
||||
payment.save
|
||||
payment.post_save(schedule&.stp_setup_intent_id)
|
||||
payment.post_save(schedule&.gateway_payment_mean&.id)
|
||||
UsersCredits::Manager.new(user: new_sub.user).reset_credits
|
||||
return new_sub
|
||||
end
|
||||
|
@ -21,7 +21,7 @@ class PaymentScheduleItemWorker
|
||||
if psi.payment_schedule.payment_method == 'card'
|
||||
### Stripe
|
||||
stripe_key = Setting.get('stripe_secret_key')
|
||||
stp_subscription = Stripe::Subscription.retrieve(psi.payment_schedule.stp_subscription_id, api_key: stripe_key)
|
||||
stp_subscription = psi.payment_schedule.gateway_subscription.retrieve
|
||||
stp_invoice = Stripe::Invoice.retrieve(stp_subscription.latest_invoice, api_key: stripe_key)
|
||||
if stp_invoice.status == 'paid'
|
||||
##### Stripe / Successfully paid
|
||||
|
@ -33,9 +33,9 @@ class StripeWorker
|
||||
|
||||
def create_or_update_stp_product(class_name, id)
|
||||
object = class_name.constantize.find(id)
|
||||
if !object.stp_product_id.nil?
|
||||
if !object.payment_gateway_object.nil?
|
||||
Stripe::Product.update(
|
||||
object.stp_product_id,
|
||||
object.payment_gateway_object.gateway_object_id,
|
||||
{ name: object.name },
|
||||
{ api_key: Setting.get('stripe_secret_key') }
|
||||
)
|
||||
@ -49,12 +49,15 @@ class StripeWorker
|
||||
}
|
||||
}, { api_key: Setting.get('stripe_secret_key') }
|
||||
)
|
||||
object.update_attributes(stp_product_id: product.id)
|
||||
pgo = PaymentGatewayObject.new(item: object)
|
||||
pgo.gateway_object = product
|
||||
pgo.save!
|
||||
puts "Stripe product was created for the #{class_name} \##{id}"
|
||||
end
|
||||
|
||||
rescue Stripe::InvalidRequestError
|
||||
STDERR.puts "WARNING: saved stp_product_id (#{object.stp_product_id}) does not match on Stripe, recreating..."
|
||||
obj_id = object.payment_gateway_object.gateway_object_id
|
||||
STDERR.puts "WARNING: saved payment_gateway_object#id (#{obj_id}) does not match on Stripe, recreating..."
|
||||
product = Stripe::Product.create(
|
||||
{
|
||||
name: object.name,
|
||||
@ -64,7 +67,9 @@ class StripeWorker
|
||||
}
|
||||
}, { api_key: Setting.get('stripe_secret_key') }
|
||||
)
|
||||
object.update_attributes(stp_product_id: product.id)
|
||||
pgo = PaymentGatewayObject.new(item: object)
|
||||
pgo.gateway_object = product
|
||||
pgo.save!
|
||||
puts "Stripe product was created for the #{class_name} \##{id}"
|
||||
end
|
||||
end
|
||||
|
@ -11,7 +11,7 @@ class SyncMembersOnStripeWorker
|
||||
User.online_payers.each_with_index do |member, index|
|
||||
logger.debug "#{index} / #{total}"
|
||||
begin
|
||||
stp_customer = Stripe::Customer.retrieve(member.stp_customer_id, api_key: Setting.get('stripe_secret_key'))
|
||||
stp_customer = member.payment_gateway_objects.gateway_object.retrieve
|
||||
StripeWorker.new.create_stripe_customer(member.id) if stp_customer.nil? || stp_customer[:deleted]
|
||||
rescue Stripe::InvalidRequestError
|
||||
StripeWorker.new.create_stripe_customer(member.id)
|
||||
|
@ -108,8 +108,8 @@ SET default_tablespace = '';
|
||||
|
||||
CREATE TABLE public.abuses (
|
||||
id integer NOT NULL,
|
||||
signaled_id integer,
|
||||
signaled_type character varying,
|
||||
signaled_id integer,
|
||||
first_name character varying,
|
||||
last_name character varying,
|
||||
email character varying,
|
||||
@ -187,8 +187,8 @@ CREATE TABLE public.addresses (
|
||||
locality character varying,
|
||||
country character varying,
|
||||
postal_code character varying,
|
||||
placeable_id integer,
|
||||
placeable_type character varying,
|
||||
placeable_id integer,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone
|
||||
);
|
||||
@ -263,8 +263,8 @@ CREATE TABLE public.ar_internal_metadata (
|
||||
|
||||
CREATE TABLE public.assets (
|
||||
id integer NOT NULL,
|
||||
viewable_id integer,
|
||||
viewable_type character varying,
|
||||
viewable_id integer,
|
||||
attachment character varying,
|
||||
type character varying,
|
||||
created_at timestamp without time zone,
|
||||
@ -504,8 +504,8 @@ ALTER SEQUENCE public.coupons_id_seq OWNED BY public.coupons.id;
|
||||
|
||||
CREATE TABLE public.credits (
|
||||
id integer NOT NULL,
|
||||
creditable_id integer,
|
||||
creditable_type character varying,
|
||||
creditable_id integer,
|
||||
plan_id integer,
|
||||
hours integer,
|
||||
created_at timestamp without time zone,
|
||||
@ -1045,8 +1045,8 @@ ALTER SEQUENCE public.invoice_items_id_seq OWNED BY public.invoice_items.id;
|
||||
|
||||
CREATE TABLE public.invoices (
|
||||
id integer NOT NULL,
|
||||
invoiced_id integer,
|
||||
invoiced_type character varying,
|
||||
invoiced_id integer,
|
||||
total integer,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone,
|
||||
@ -1223,15 +1223,15 @@ ALTER SEQUENCE public.machines_id_seq OWNED BY public.machines.id;
|
||||
CREATE TABLE public.notifications (
|
||||
id integer NOT NULL,
|
||||
receiver_id integer,
|
||||
attached_object_id integer,
|
||||
attached_object_type character varying,
|
||||
attached_object_id integer,
|
||||
notification_type_id integer,
|
||||
is_read boolean DEFAULT false,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone,
|
||||
receiver_type character varying,
|
||||
is_send boolean DEFAULT false,
|
||||
meta_data jsonb DEFAULT '{}'::jsonb
|
||||
meta_data jsonb DEFAULT '"{}"'::jsonb
|
||||
);
|
||||
|
||||
|
||||
@ -1687,8 +1687,8 @@ CREATE TABLE public.prices (
|
||||
id integer NOT NULL,
|
||||
group_id integer,
|
||||
plan_id integer,
|
||||
priceable_id integer,
|
||||
priceable_type character varying,
|
||||
priceable_id integer,
|
||||
amount integer,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL
|
||||
@ -2003,8 +2003,8 @@ CREATE TABLE public.reservations (
|
||||
message text,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone,
|
||||
reservable_id integer,
|
||||
reservable_type character varying,
|
||||
reservable_id integer,
|
||||
nb_reserve_places integer,
|
||||
statistic_profile_id integer
|
||||
);
|
||||
@ -2036,8 +2036,8 @@ ALTER SEQUENCE public.reservations_id_seq OWNED BY public.reservations.id;
|
||||
CREATE TABLE public.roles (
|
||||
id integer NOT NULL,
|
||||
name character varying,
|
||||
resource_id integer,
|
||||
resource_type character varying,
|
||||
resource_id integer,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone
|
||||
);
|
||||
@ -2969,8 +2969,8 @@ CREATE TABLE public.users_roles (
|
||||
CREATE TABLE public.wallet_transactions (
|
||||
id integer NOT NULL,
|
||||
wallet_id integer,
|
||||
transactable_id integer,
|
||||
transactable_type character varying,
|
||||
transactable_id integer,
|
||||
transaction_type character varying,
|
||||
amount integer,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
@ -4074,6 +4074,14 @@ ALTER TABLE ONLY public.roles
|
||||
ADD CONSTRAINT roles_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.schema_migrations
|
||||
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: settings settings_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@ -5152,29 +5160,6 @@ CREATE INDEX profiles_lower_unaccent_last_name_trgm_idx ON public.profiles USING
|
||||
CREATE INDEX projects_search_vector_idx ON public.projects USING gin (search_vector);
|
||||
|
||||
|
||||
--
|
||||
-- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: accounting_periods accounting_periods_del_protect; Type: RULE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE RULE accounting_periods_del_protect AS
|
||||
ON DELETE TO public.accounting_periods DO INSTEAD NOTHING;
|
||||
|
||||
|
||||
--
|
||||
-- Name: accounting_periods accounting_periods_upd_protect; Type: RULE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE RULE accounting_periods_upd_protect AS
|
||||
ON UPDATE TO public.accounting_periods DO INSTEAD NOTHING;
|
||||
|
||||
|
||||
--
|
||||
-- Name: projects projects_search_content_trigger; Type: TRIGGER; Schema: public; Owner: -
|
||||
--
|
||||
@ -5717,7 +5702,6 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20140605125131'),
|
||||
('20140605142133'),
|
||||
('20140605151442'),
|
||||
('20140606133116'),
|
||||
('20140609092700'),
|
||||
('20140609092827'),
|
||||
('20140610153123'),
|
||||
@ -5786,14 +5770,12 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20150507075620'),
|
||||
('20150512123546'),
|
||||
('20150520132030'),
|
||||
('20150520133409'),
|
||||
('20150526130729'),
|
||||
('20150527153312'),
|
||||
('20150529113555'),
|
||||
('20150601125944'),
|
||||
('20150603104502'),
|
||||
('20150603104658'),
|
||||
('20150603133050'),
|
||||
('20150604081757'),
|
||||
('20150604131525'),
|
||||
('20150608142234'),
|
||||
@ -5875,7 +5857,6 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20160905142700'),
|
||||
('20160906094739'),
|
||||
('20160906094847'),
|
||||
('20160906145713'),
|
||||
('20160915105234'),
|
||||
('20161123104604'),
|
||||
('20170109085345'),
|
||||
|
@ -18,4 +18,5 @@ fi
|
||||
RAILS_ENV='test' bin/rails db:drop
|
||||
RAILS_ENV='test' bin/rails db:create
|
||||
RAILS_ENV='test' bin/rails db:migrate
|
||||
clear
|
||||
STRIPE_PUBLISHABLE_KEY="$stripe_public_key" STRIPE_API_KEY="$stripe_secret_key" RAILS_ENV='test' bundle exec bin/rails test "$@"
|
||||
|
6
test/fixtures/invoices.yml
vendored
6
test/fixtures/invoices.yml
vendored
@ -3,7 +3,6 @@ invoice_1:
|
||||
id: 1
|
||||
invoiced_id: 1
|
||||
invoiced_type: Subscription
|
||||
stp_invoice_id: in_17wpf92sOmf47Nz9itj6vmJw
|
||||
total: 10000
|
||||
created_at: 2012-03-12 11:03:31.651441000 Z
|
||||
updated_at: 2012-03-12 11:03:31.651441000 Z
|
||||
@ -24,7 +23,6 @@ invoice_2:
|
||||
id: 2
|
||||
invoiced_id: 2
|
||||
invoiced_type: Subscription
|
||||
stp_invoice_id:
|
||||
total: 2000
|
||||
created_at: 2012-03-12 13:40:22.342717000 Z
|
||||
updated_at: 2012-03-12 13:40:22.342717000 Z
|
||||
@ -45,7 +43,6 @@ invoice_3:
|
||||
id: 3
|
||||
invoiced_id: 3
|
||||
invoiced_type: Subscription
|
||||
stp_invoice_id:
|
||||
total: 3000
|
||||
created_at: 2015-06-10 11:20:01.341130000 Z
|
||||
updated_at: 2015-06-10 11:20:01.341130000 Z
|
||||
@ -67,7 +64,6 @@ invoice_4:
|
||||
id: 4
|
||||
invoiced_id: 1
|
||||
invoiced_type: Reservation
|
||||
stp_invoice_id:
|
||||
total: 0
|
||||
created_at: 2016-04-05 08:35:52.931187000 Z
|
||||
updated_at: 2016-04-05 08:35:52.931187000 Z
|
||||
@ -88,7 +84,6 @@ invoice_5:
|
||||
id: 5
|
||||
invoiced_id: 2
|
||||
invoiced_type: Reservation
|
||||
stp_invoice_id:
|
||||
total: 1500
|
||||
created_at: 2016-04-05 08:36:46.853368000 Z
|
||||
updated_at: 2016-04-05 08:36:46.853368000 Z
|
||||
@ -109,7 +104,6 @@ invoice_6:
|
||||
id: 6
|
||||
invoiced_id: 4
|
||||
invoiced_type: Subscription
|
||||
stp_invoice_id:
|
||||
total: 3000
|
||||
created_at: 2021-01-04 14:51:21.616153182 Z
|
||||
updated_at: 2021-01-04 14:51:21.616153182 Z
|
||||
|
6
test/fixtures/machines.yml
vendored
6
test/fixtures/machines.yml
vendored
@ -22,7 +22,6 @@ machine_1:
|
||||
created_at: 2016-04-04 14:11:34.210242000 Z
|
||||
updated_at: 2016-04-04 14:11:34.210242000 Z
|
||||
slug: decoupeuse-laser
|
||||
stp_product_id: prod_IZPyHpMCl38iQl
|
||||
|
||||
machine_2:
|
||||
id: 2
|
||||
@ -39,7 +38,6 @@ machine_2:
|
||||
created_at: 2016-04-04 14:11:34.274025000 Z
|
||||
updated_at: 2016-04-04 14:11:34.274025000 Z
|
||||
slug: decoupeuse-vinyle
|
||||
stp_product_id: prod_IZPyPShaaRgSML
|
||||
|
||||
machine_3:
|
||||
id: 3
|
||||
@ -56,7 +54,6 @@ machine_3:
|
||||
created_at: 2016-04-04 14:11:34.304247000 Z
|
||||
updated_at: 2016-04-04 14:11:34.304247000 Z
|
||||
slug: shopbot-grande-fraiseuse
|
||||
stp_product_id: prod_IZPyEjmdfMowhY
|
||||
|
||||
machine_4:
|
||||
id: 4
|
||||
@ -70,7 +67,6 @@ machine_4:
|
||||
created_at: 2001-01-01 14:11:34.341810000 Z
|
||||
updated_at: 2001-01-01 14:11:34.341810000 Z
|
||||
slug: imprimante-3d
|
||||
stp_product_id: prod_IZPy85vZOQpAo5
|
||||
|
||||
machine_5:
|
||||
id: 5
|
||||
@ -93,7 +89,6 @@ machine_5:
|
||||
created_at: 2016-04-04 14:11:34.379481000 Z
|
||||
updated_at: 2016-04-04 14:11:34.379481000 Z
|
||||
slug: petite-fraiseuse
|
||||
stp_product_id: prod_IZPyBJEgbcpWMC
|
||||
|
||||
machine_6:
|
||||
id: 6
|
||||
@ -128,4 +123,3 @@ machine_6:
|
||||
created_at: 2016-04-04 14:11:34.424740000 Z
|
||||
updated_at: 2016-04-04 14:11:34.424740000 Z
|
||||
slug: form1-imprimante-3d
|
||||
stp_product_id: prod_IZPyjCzvLmLWAz
|
||||
|
156
test/fixtures/payment_gateway_objects.yml
vendored
156
test/fixtures/payment_gateway_objects.yml
vendored
@ -6,6 +6,156 @@ pgo_1:
|
||||
|
||||
pgo2:
|
||||
item_type: 'Subscription'
|
||||
item_id: 1
|
||||
gateway_object_type: 'Stripe::Subscription'
|
||||
gateway_object_id: 'sub_8DGB4ErIc2asOv'
|
||||
item_id: 1
|
||||
gateway_object_type: 'Stripe::Subscription'
|
||||
gateway_object_id: 'sub_8DGB4ErIc2asOv'
|
||||
|
||||
pgo3:
|
||||
item_type: 'Invoice'
|
||||
item_id: 1
|
||||
gateway_object_type: 'Stripe::Invoice'
|
||||
gateway_object_id: 'in_17wpf92sOmf47Nz9itj6vmJw'
|
||||
|
||||
pgo4:
|
||||
item_type: 'Plan'
|
||||
item_id: 1
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyXhfyNiGkWR'
|
||||
|
||||
pgo5:
|
||||
item_type: 'Plan'
|
||||
item_id: 2
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPykam7a4satn'
|
||||
|
||||
pgo6:
|
||||
item_type: 'Plan'
|
||||
item_id: 3
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyM4N36h86G0'
|
||||
|
||||
pgo7:
|
||||
item_type: 'Plan'
|
||||
item_id: 4
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZQAhb9nLu4jfN'
|
||||
|
||||
pgo8:
|
||||
item_type: 'Machine'
|
||||
item_id: 1
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyHpMCl38iQl'
|
||||
|
||||
pgo9:
|
||||
item_type: 'Machine'
|
||||
item_id: 2
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyPShaaRgSML'
|
||||
|
||||
pgo10:
|
||||
item_type: 'Machine'
|
||||
item_id: 3
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyEjmdfMowhY'
|
||||
|
||||
pgo11:
|
||||
item_type: 'Machine'
|
||||
item_id: 4
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPy85vZOQpAo5'
|
||||
|
||||
pgo12:
|
||||
item_type: 'Machine'
|
||||
item_id: 5
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyBJEgbcpWMC'
|
||||
|
||||
pgo13:
|
||||
item_type: 'Machine'
|
||||
item_id: 6
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyjCzvLmLWAz'
|
||||
|
||||
pgo14:
|
||||
item_type: 'Space'
|
||||
item_id: 1
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyHjIb2owoB8'
|
||||
|
||||
pgo15:
|
||||
item_type: 'Training'
|
||||
item_id: 1
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyXw6BDBBFOg'
|
||||
|
||||
pgo16:
|
||||
item_type: 'Training'
|
||||
item_id: 2
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPytTl1wSB5jH'
|
||||
|
||||
pgo17:
|
||||
item_type: 'Training'
|
||||
item_id: 3
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyAA1A4QfEyL'
|
||||
|
||||
pgo18:
|
||||
item_type: 'Training'
|
||||
item_id: 4
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyU27NjDSmqB'
|
||||
|
||||
pgo19:
|
||||
item_type: 'Training'
|
||||
item_id: 5
|
||||
gateway_object_type: 'Stripe::Product'
|
||||
gateway_object_id: 'prod_IZPyvdgQHMByB3'
|
||||
|
||||
pgo20:
|
||||
item_type: 'User'
|
||||
item_id: 1
|
||||
gateway_object_type: 'Stripe::Customer'
|
||||
gateway_object_id: 'cus_8CyNk3UTi8lvCc'
|
||||
|
||||
pgo21:
|
||||
item_type: 'User'
|
||||
item_id: 2
|
||||
gateway_object_type: 'Stripe::Customer'
|
||||
gateway_object_id: 'cus_8Di1wjdVktv5kt'
|
||||
|
||||
pgo22:
|
||||
item_type: 'User'
|
||||
item_id: 3
|
||||
gateway_object_type: 'Stripe::Customer'
|
||||
gateway_object_id: 'cus_8CzHcwBJtlA3IL'
|
||||
|
||||
pgo23:
|
||||
item_type: 'User'
|
||||
item_id: 4
|
||||
gateway_object_type: 'Stripe::Customer'
|
||||
gateway_object_id: 'cus_8CzKe50I0J1gaI'
|
||||
|
||||
pgo24:
|
||||
item_type: 'User'
|
||||
item_id: 5
|
||||
gateway_object_type: 'Stripe::Customer'
|
||||
gateway_object_id: 'cus_8CzNtM08NVlSGN'
|
||||
|
||||
pgo25:
|
||||
item_type: 'User'
|
||||
item_id: 6
|
||||
gateway_object_type: 'Stripe::Customer'
|
||||
gateway_object_id: 'cus_8CzQK5uXPeyh4K'
|
||||
|
||||
pgo26:
|
||||
item_type: 'User'
|
||||
item_id: 7
|
||||
gateway_object_type: 'Stripe::Customer'
|
||||
gateway_object_id: 'cus_8E2ys9zDZgetWX'
|
||||
|
||||
pgo27:
|
||||
item_type: 'User'
|
||||
item_id: 8
|
||||
gateway_object_type: 'Stripe::Customer'
|
||||
gateway_object_id: 'cus_IhIynmoJbzLpwX'
|
||||
|
4
test/fixtures/plans.yml
vendored
4
test/fixtures/plans.yml
vendored
@ -16,7 +16,6 @@ plan_1:
|
||||
ui_weight: 1
|
||||
interval_count: 1
|
||||
slug: mensuel
|
||||
stp_product_id: prod_IZPyXhfyNiGkWR
|
||||
|
||||
plan_2:
|
||||
id: 2
|
||||
@ -35,7 +34,6 @@ plan_2:
|
||||
ui_weight: 5
|
||||
interval_count: 2
|
||||
slug: sleede
|
||||
stp_product_id: prod_IZPykam7a4satn
|
||||
|
||||
plan_3:
|
||||
id: 3
|
||||
@ -55,7 +53,6 @@ plan_3:
|
||||
ui_weight: 0
|
||||
interval_count: 1*
|
||||
slug: mensuel-tarif-reduit
|
||||
stp_product_id: prod_IZPyM4N36h86G0
|
||||
|
||||
plan_schedulable:
|
||||
id: 4
|
||||
@ -75,4 +72,3 @@ plan_schedulable:
|
||||
interval_count: 1
|
||||
monthly_payment: true
|
||||
slug: abonnement-mensualisable
|
||||
stp_product_id: prod_IZQAhb9nLu4jfN
|
||||
|
1
test/fixtures/spaces.yml
vendored
1
test/fixtures/spaces.yml
vendored
@ -7,4 +7,3 @@ space_1:
|
||||
created_at: 2017-02-15 15:55:04.123928000 Z
|
||||
updated_at: 2017-02-15 15:55:04.123928000 Z
|
||||
characteristics: Scie à chantourner, rabot, dégauchisseuse, chanfreineuse et pyrograveur
|
||||
stp_product_id: prod_IZPyHjIb2owoB8
|
||||
|
5
test/fixtures/trainings.yml
vendored
5
test/fixtures/trainings.yml
vendored
@ -7,7 +7,6 @@ training_1:
|
||||
nb_total_places:
|
||||
slug: formation-imprimante-3d
|
||||
description:
|
||||
stp_product_id: prod_IZPyXw6BDBBFOg
|
||||
|
||||
training_2:
|
||||
id: 2
|
||||
@ -17,7 +16,6 @@ training_2:
|
||||
nb_total_places:
|
||||
slug: formation-laser-vinyle
|
||||
description:
|
||||
stp_product_id: prod_IZPytTl1wSB5jH
|
||||
|
||||
training_3:
|
||||
id: 3
|
||||
@ -27,7 +25,6 @@ training_3:
|
||||
nb_total_places:
|
||||
slug: formation-petite-fraiseuse-numerique
|
||||
description:
|
||||
stp_product_id: prod_IZPyAA1A4QfEyL
|
||||
|
||||
training_4:
|
||||
id: 4
|
||||
@ -37,7 +34,6 @@ training_4:
|
||||
nb_total_places:
|
||||
slug: formation-shopbot-grande-fraiseuse
|
||||
description:
|
||||
stp_product_id: prod_IZPyU27NjDSmqB
|
||||
|
||||
training_5:
|
||||
id: 5
|
||||
@ -47,4 +43,3 @@ training_5:
|
||||
nb_total_places:
|
||||
slug: formation-logiciel-2d
|
||||
description:
|
||||
stp_product_id: prod_IZPyvdgQHMByB3
|
||||
|
230
test/fixtures/users.yml
vendored
230
test/fixtures/users.yml
vendored
@ -1,3 +1,34 @@
|
||||
user_1:
|
||||
id: 1
|
||||
username: admin
|
||||
email: admin@fab-manager.com
|
||||
encrypted_password: "$2a$10$LtQ2OggropcXpmcsPTEPruuGZrwuFYGOo8qjh.po91YDna/K4/Bbe"
|
||||
reset_password_token:
|
||||
reset_password_sent_at:
|
||||
remember_created_at:
|
||||
sign_in_count: 8
|
||||
current_sign_in_at: 2016-04-05 08:36:08.361260000 Z
|
||||
last_sign_in_at: 2016-04-05 08:34:28.227054000 Z
|
||||
current_sign_in_ip: 127.0.0.1
|
||||
last_sign_in_ip: 127.0.0.1
|
||||
confirmation_token:
|
||||
confirmed_at: 2016-04-05 08:40:21.514533000 Z
|
||||
confirmation_sent_at: 2001-01-01 14:11:33.852719000 Z
|
||||
unconfirmed_email:
|
||||
failed_attempts: 0
|
||||
unlock_token:
|
||||
locked_at:
|
||||
created_at: 2001-01-01 14:11:33.852719000 Z
|
||||
updated_at: 2016-04-05 08:36:08.362215000 Z
|
||||
is_allow_contact: true
|
||||
group_id: 3
|
||||
slug: admin
|
||||
is_active: true
|
||||
provider:
|
||||
uid:
|
||||
auth_token:
|
||||
merged_at:
|
||||
is_allow_newsletter: true
|
||||
|
||||
user_2:
|
||||
id: 2
|
||||
@ -23,7 +54,6 @@ user_2:
|
||||
updated_at: 2016-04-04 15:00:43.556308000 Z
|
||||
is_allow_contact: true
|
||||
group_id: 1
|
||||
stp_customer_id: cus_8Di1wjdVktv5kt
|
||||
slug: jdupond
|
||||
is_active: true
|
||||
provider:
|
||||
@ -32,105 +62,6 @@ user_2:
|
||||
merged_at:
|
||||
is_allow_newsletter: true
|
||||
|
||||
user_4:
|
||||
id: 4
|
||||
username: kdumas
|
||||
email: kevin.dumas@orange.fr
|
||||
encrypted_password: "$2a$10$N6Q4SHkkUtwlnMNFvN6nF.rkmLFTIPsARk7xEuR1Dws7Dy2sSrSOW"
|
||||
reset_password_token:
|
||||
reset_password_sent_at:
|
||||
remember_created_at:
|
||||
sign_in_count: 0
|
||||
current_sign_in_at:
|
||||
last_sign_in_at:
|
||||
current_sign_in_ip:
|
||||
last_sign_in_ip:
|
||||
confirmation_token:
|
||||
confirmed_at: 2016-04-04 15:11:02.968494000 Z
|
||||
confirmation_sent_at: 2016-04-04 15:10:42.376191000 Z
|
||||
unconfirmed_email:
|
||||
failed_attempts: 0
|
||||
unlock_token:
|
||||
locked_at:
|
||||
created_at: 2016-04-04 15:10:42.340868000 Z
|
||||
updated_at: 2016-04-04 15:11:02.969182000 Z
|
||||
is_allow_contact: true
|
||||
group_id: 2
|
||||
stp_customer_id: cus_8CzKe50I0J1gaI
|
||||
slug: kdumas
|
||||
is_active: true
|
||||
provider:
|
||||
uid:
|
||||
auth_token:
|
||||
merged_at:
|
||||
is_allow_newsletter: false
|
||||
|
||||
user_6:
|
||||
id: 6
|
||||
username: GilbertPartenaire
|
||||
email: gilbert.partenaire@nicolas.com
|
||||
encrypted_password: "$2a$10$UtWcIYMd2aOtQjw6OFL4cuMV1MB20Bfs/opzJDqWXqu8woUo.2cLu"
|
||||
reset_password_token:
|
||||
reset_password_sent_at:
|
||||
remember_created_at:
|
||||
sign_in_count: 0
|
||||
current_sign_in_at:
|
||||
last_sign_in_at:
|
||||
current_sign_in_ip:
|
||||
last_sign_in_ip:
|
||||
confirmation_token:
|
||||
confirmed_at: 2016-04-04 15:18:14.124111000 Z
|
||||
confirmation_sent_at: 2016-04-04 15:17:12.522028000 Z
|
||||
unconfirmed_email:
|
||||
failed_attempts: 0
|
||||
unlock_token:
|
||||
locked_at:
|
||||
created_at: 2016-04-04 15:17:12.522028000 Z
|
||||
updated_at: 2016-04-04 15:17:12.522028000 Z
|
||||
is_allow_contact: true
|
||||
group_id: 1
|
||||
stp_customer_id: cus_8CzQK5uXPeyh4K
|
||||
slug: gilbertpartenaire
|
||||
is_active: true
|
||||
provider:
|
||||
uid:
|
||||
auth_token:
|
||||
merged_at:
|
||||
is_allow_newsletter: true
|
||||
|
||||
user_5:
|
||||
id: 5
|
||||
username: vlonchamp
|
||||
email: vanessa.lonchamp@sfr.fr
|
||||
encrypted_password: "$2a$10$HOEk.QyGwpd9nsk2gVXGSuAxig9jMrNFHVqYMW1.Sp41EtN7rdBbG"
|
||||
reset_password_token:
|
||||
reset_password_sent_at:
|
||||
remember_created_at:
|
||||
sign_in_count: 1
|
||||
current_sign_in_at: 2016-04-04 15:34:23.343596000 Z
|
||||
last_sign_in_at: 2016-04-04 15:34:23.343596000 Z
|
||||
current_sign_in_ip: 37.64.230.6
|
||||
last_sign_in_ip: 37.67.211.2
|
||||
confirmation_token: 59cfd407491c4e1d95a9f91f81e710a62a83a6fd7171ad22823b4c4395312c4d
|
||||
confirmed_at: 2016-04-04 15:18:12.122101000 Z
|
||||
confirmation_sent_at: 2016-04-04 15:14:08.599603000 Z
|
||||
unconfirmed_email:
|
||||
failed_attempts: 0
|
||||
unlock_token:
|
||||
locked_at:
|
||||
created_at: 2016-04-04 15:14:08.563152000 Z
|
||||
updated_at: 2016-04-04 15:34:23.344613000 Z
|
||||
is_allow_contact: true
|
||||
group_id: 2
|
||||
stp_customer_id: cus_8CzNtM08NVlSGN
|
||||
slug: vlonchamp
|
||||
is_active: true
|
||||
provider:
|
||||
uid:
|
||||
auth_token:
|
||||
merged_at:
|
||||
is_allow_newsletter: true
|
||||
|
||||
user_3:
|
||||
id: 3
|
||||
username: pdurand
|
||||
@ -155,7 +86,6 @@ user_3:
|
||||
updated_at: 2016-04-05 08:35:05.678582000 Z
|
||||
is_allow_contact: false
|
||||
group_id: 1
|
||||
stp_customer_id: cus_8CzHcwBJtlA3IL
|
||||
slug: pdurand
|
||||
is_active: true
|
||||
provider:
|
||||
@ -164,32 +94,63 @@ user_3:
|
||||
merged_at:
|
||||
is_allow_newsletter: false
|
||||
|
||||
user_1:
|
||||
id: 1
|
||||
username: admin
|
||||
email: admin@fab-manager.com
|
||||
encrypted_password: "$2a$10$LtQ2OggropcXpmcsPTEPruuGZrwuFYGOo8qjh.po91YDna/K4/Bbe"
|
||||
user_4:
|
||||
id: 4
|
||||
username: kdumas
|
||||
email: kevin.dumas@orange.fr
|
||||
encrypted_password: "$2a$10$N6Q4SHkkUtwlnMNFvN6nF.rkmLFTIPsARk7xEuR1Dws7Dy2sSrSOW"
|
||||
reset_password_token:
|
||||
reset_password_sent_at:
|
||||
remember_created_at:
|
||||
sign_in_count: 8
|
||||
current_sign_in_at: 2016-04-05 08:36:08.361260000 Z
|
||||
last_sign_in_at: 2016-04-05 08:34:28.227054000 Z
|
||||
current_sign_in_ip: 127.0.0.1
|
||||
last_sign_in_ip: 127.0.0.1
|
||||
sign_in_count: 0
|
||||
current_sign_in_at:
|
||||
last_sign_in_at:
|
||||
current_sign_in_ip:
|
||||
last_sign_in_ip:
|
||||
confirmation_token:
|
||||
confirmed_at: 2016-04-05 08:40:21.514533000 Z
|
||||
confirmation_sent_at: 2001-01-01 14:11:33.852719000 Z
|
||||
confirmed_at: 2016-04-04 15:11:02.968494000 Z
|
||||
confirmation_sent_at: 2016-04-04 15:10:42.376191000 Z
|
||||
unconfirmed_email:
|
||||
failed_attempts: 0
|
||||
unlock_token:
|
||||
locked_at:
|
||||
created_at: 2001-01-01 14:11:33.852719000 Z
|
||||
updated_at: 2016-04-05 08:36:08.362215000 Z
|
||||
created_at: 2016-04-04 15:10:42.340868000 Z
|
||||
updated_at: 2016-04-04 15:11:02.969182000 Z
|
||||
is_allow_contact: true
|
||||
group_id: 3
|
||||
stp_customer_id: cus_8CyNk3UTi8lvCc
|
||||
slug: admin
|
||||
group_id: 2
|
||||
slug: kdumas
|
||||
is_active: true
|
||||
provider:
|
||||
uid:
|
||||
auth_token:
|
||||
merged_at:
|
||||
is_allow_newsletter: false
|
||||
|
||||
user_5:
|
||||
id: 5
|
||||
username: vlonchamp
|
||||
email: vanessa.lonchamp@sfr.fr
|
||||
encrypted_password: "$2a$10$HOEk.QyGwpd9nsk2gVXGSuAxig9jMrNFHVqYMW1.Sp41EtN7rdBbG"
|
||||
reset_password_token:
|
||||
reset_password_sent_at:
|
||||
remember_created_at:
|
||||
sign_in_count: 1
|
||||
current_sign_in_at: 2016-04-04 15:34:23.343596000 Z
|
||||
last_sign_in_at: 2016-04-04 15:34:23.343596000 Z
|
||||
current_sign_in_ip: 37.64.230.6
|
||||
last_sign_in_ip: 37.67.211.2
|
||||
confirmation_token: 59cfd407491c4e1d95a9f91f81e710a62a83a6fd7171ad22823b4c4395312c4d
|
||||
confirmed_at: 2016-04-04 15:18:12.122101000 Z
|
||||
confirmation_sent_at: 2016-04-04 15:14:08.599603000 Z
|
||||
unconfirmed_email:
|
||||
failed_attempts: 0
|
||||
unlock_token:
|
||||
locked_at:
|
||||
created_at: 2016-04-04 15:14:08.563152000 Z
|
||||
updated_at: 2016-04-04 15:34:23.344613000 Z
|
||||
is_allow_contact: true
|
||||
group_id: 2
|
||||
slug: vlonchamp
|
||||
is_active: true
|
||||
provider:
|
||||
uid:
|
||||
@ -197,6 +158,37 @@ user_1:
|
||||
merged_at:
|
||||
is_allow_newsletter: true
|
||||
|
||||
user_6:
|
||||
id: 6
|
||||
username: GilbertPartenaire
|
||||
email: gilbert.partenaire@nicolas.com
|
||||
encrypted_password: "$2a$10$UtWcIYMd2aOtQjw6OFL4cuMV1MB20Bfs/opzJDqWXqu8woUo.2cLu"
|
||||
reset_password_token:
|
||||
reset_password_sent_at:
|
||||
remember_created_at:
|
||||
sign_in_count: 0
|
||||
current_sign_in_at:
|
||||
last_sign_in_at:
|
||||
current_sign_in_ip:
|
||||
last_sign_in_ip:
|
||||
confirmation_token:
|
||||
confirmed_at: 2016-04-04 15:18:14.124111000 Z
|
||||
confirmation_sent_at: 2016-04-04 15:17:12.522028000 Z
|
||||
unconfirmed_email:
|
||||
failed_attempts: 0
|
||||
unlock_token:
|
||||
locked_at:
|
||||
created_at: 2016-04-04 15:17:12.522028000 Z
|
||||
updated_at: 2016-04-04 15:17:12.522028000 Z
|
||||
is_allow_contact: true
|
||||
group_id: 1
|
||||
slug: gilbertpartenaire
|
||||
is_active: true
|
||||
provider:
|
||||
uid:
|
||||
auth_token:
|
||||
merged_at:
|
||||
is_allow_newsletter: true
|
||||
|
||||
user_7:
|
||||
id: 7
|
||||
@ -222,7 +214,6 @@ user_7:
|
||||
updated_at: 2016-04-07 11:00:37.643112000 Z
|
||||
is_allow_contact: true
|
||||
group_id: 1
|
||||
stp_customer_id: cus_8E2ys9zDZgetWX
|
||||
slug: lseguin
|
||||
is_active: true
|
||||
provider:
|
||||
@ -255,7 +246,6 @@ user_8:
|
||||
updated_at: 2021-01-04 14:36:39.729052932 Z
|
||||
is_allow_contact: true
|
||||
group_id: 1
|
||||
stp_customer_id: cus_IhIynmoJbzLpwX
|
||||
slug: atiermoulin
|
||||
is_active: true
|
||||
provider:
|
||||
|
@ -64,8 +64,8 @@ module Events
|
||||
# Now, let's make a reservation on this event
|
||||
post '/api/reservations',
|
||||
params: {
|
||||
customer_id: User.find_by(username: 'pdurand').id,
|
||||
reservation: {
|
||||
user_id: User.find_by(username: 'pdurand').id,
|
||||
reservable_id: e.id,
|
||||
reservable_type: 'Event',
|
||||
nb_reserve_places: 2,
|
||||
@ -158,8 +158,8 @@ module Events
|
||||
# Now, let's make a reservation on this event
|
||||
post '/api/reservations',
|
||||
params: {
|
||||
customer_id: User.find_by(username: 'lseguin').id,
|
||||
reservation: {
|
||||
user_id: User.find_by(username: 'lseguin').id,
|
||||
reservable_id: e.id,
|
||||
reservable_type: 'Event',
|
||||
nb_reserve_places: 4,
|
||||
|
@ -29,9 +29,9 @@ module Events
|
||||
post '/api/stripe/confirm_payment',
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
customer_id: User.find_by(username: 'vlonchamp').id,
|
||||
cart_items: {
|
||||
reservation: {
|
||||
user_id: User.find_by(username: 'vlonchamp').id,
|
||||
reservable_id: radio.id,
|
||||
reservable_type: 'Event',
|
||||
nb_reserve_places: 2,
|
||||
@ -78,7 +78,7 @@ module Events
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
refute invoice.stp_payment_intent_id.blank?
|
||||
refute invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
assert_equal 43_350, invoice.total # total minus coupon
|
||||
|
||||
@ -94,7 +94,7 @@ module Events
|
||||
assert_invoice_pdf invoice
|
||||
|
||||
VCR.use_cassette('reserve_event_with_many_prices_and_payment_means_retrieve_invoice_from_stripe') do
|
||||
stp_intent = Stripe::PaymentIntent.retrieve(invoice.stp_payment_intent_id, api_key: Setting.get('stripe_secret_key'))
|
||||
stp_intent = invoice.payment_gateway_object.gateway_object.retrieve
|
||||
assert_equal stp_intent.amount, (invoice.total - invoice.wallet_amount) # total minus coupon minus wallet = amount really payed by the user
|
||||
end
|
||||
|
||||
|
@ -14,8 +14,8 @@ module Prices
|
||||
|
||||
post '/api/prices/compute',
|
||||
params: {
|
||||
customer_id: user.id,
|
||||
reservation: {
|
||||
user_id: user.id,
|
||||
reservable_id: printer_training.id,
|
||||
reservable_type: printer_training.class.name,
|
||||
slots_attributes: [
|
||||
@ -49,11 +49,10 @@ module Prices
|
||||
|
||||
post '/api/prices/compute',
|
||||
params: {
|
||||
customer_id: user.id,
|
||||
reservation: {
|
||||
user_id: user.id,
|
||||
reservable_id: laser.id,
|
||||
reservable_type: laser.class.name,
|
||||
plan_id: plan.id,
|
||||
slots_attributes: [
|
||||
{
|
||||
availability_id: availability.id,
|
||||
@ -68,6 +67,9 @@ module Prices
|
||||
start_at: (availability.start_at + 1.hour).strftime('%Y-%m-%d %H:%M:%S.%9N Z')
|
||||
}
|
||||
]
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}.to_json,
|
||||
headers: default_headers
|
||||
|
@ -19,18 +19,20 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_items_count = InvoiceItem.count
|
||||
users_credit_count = UsersCredit.count
|
||||
|
||||
post reservations_path, params: { reservation: {
|
||||
user_id: @user_without_subscription.id,
|
||||
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
|
||||
post reservations_path, 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
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
assert_equal 201, response.status
|
||||
@ -52,7 +54,7 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
assert invoice.stp_payment_intent_id.blank?
|
||||
assert invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
|
||||
# invoice_items assertions
|
||||
@ -76,18 +78,20 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_count = Invoice.count
|
||||
invoice_items_count = InvoiceItem.count
|
||||
|
||||
post reservations_path, params: { reservation: {
|
||||
user_id: @user_without_subscription.id,
|
||||
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
|
||||
post reservations_path, 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
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
assert_equal 201, response.status
|
||||
@ -108,7 +112,7 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
assert invoice.stp_payment_intent_id.blank?
|
||||
assert invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
# invoice_items
|
||||
invoice_item = InvoiceItem.last
|
||||
@ -133,23 +137,25 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_items_count = InvoiceItem.count
|
||||
users_credit_count = UsersCredit.count
|
||||
|
||||
post reservations_path, params: { reservation: {
|
||||
user_id: @user_with_subscription.id,
|
||||
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
|
||||
post reservations_path, 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
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
assert_equal 201, response.status
|
||||
@ -172,7 +178,7 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
assert invoice.stp_payment_intent_id.blank?
|
||||
assert invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
|
||||
# invoice_items assertions
|
||||
@ -206,18 +212,20 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_items_count = InvoiceItem.count
|
||||
users_credit_count = UsersCredit.count
|
||||
|
||||
post reservations_path, params: { reservation: {
|
||||
user_id: @vlonchamp.id,
|
||||
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
|
||||
post reservations_path, 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
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
assert_equal 201, response.status
|
||||
@ -239,7 +247,7 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
assert invoice.stp_payment_intent_id.blank?
|
||||
assert invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
|
||||
# invoice_items assertions
|
||||
@ -276,19 +284,23 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
users_credit_count = UsersCredit.count
|
||||
wallet_transactions_count = WalletTransaction.count
|
||||
|
||||
post reservations_path, params: { reservation: {
|
||||
user_id: @vlonchamp.id,
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
plan_id: plan.id,
|
||||
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
|
||||
post reservations_path, 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
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
assert_equal 201, response.status
|
||||
@ -312,7 +324,7 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
assert invoice.stp_payment_intent_id.blank?
|
||||
assert invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
assert_equal invoice.total, 2000
|
||||
|
||||
@ -343,18 +355,20 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_items_count = InvoiceItem.count
|
||||
users_credit_count = UsersCredit.count
|
||||
|
||||
post reservations_path, params: { reservation: {
|
||||
user_id: @vlonchamp.id,
|
||||
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
|
||||
post reservations_path, 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
|
||||
}
|
||||
]
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
assert_equal 201, response.status
|
||||
@ -386,20 +400,24 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
invoice_items_count = InvoiceItem.count
|
||||
users_credit_count = UsersCredit.count
|
||||
|
||||
post reservations_path, params: { reservation: {
|
||||
user_id: @user_without_subscription.id,
|
||||
plan_id: plan.id,
|
||||
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
|
||||
}
|
||||
]
|
||||
} }.to_json, headers: default_headers
|
||||
post reservations_path, 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
|
||||
}
|
||||
]
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
|
||||
# general assertions
|
||||
assert_equal 201, response.status
|
||||
@ -431,7 +449,7 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
assert invoice.stp_payment_intent_id.blank?
|
||||
assert invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
assert_equal plan.amount, invoice.total
|
||||
|
||||
@ -463,21 +481,25 @@ 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: { reservation: {
|
||||
user_id: @user_without_subscription.id,
|
||||
post reservations_path, params: {
|
||||
payment_method: 'check',
|
||||
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
|
||||
}
|
||||
],
|
||||
plan_id: plan.id,
|
||||
payment_schedule: true
|
||||
} }.to_json, headers: default_headers
|
||||
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
|
||||
}
|
||||
]
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
|
||||
# get the objects
|
||||
@ -513,8 +535,7 @@ class Reservations::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
# payment schedule assertions
|
||||
assert_not_nil payment_schedule.reference
|
||||
assert_equal 'check', payment_schedule.payment_method
|
||||
assert_nil payment_schedule.stp_subscription_id
|
||||
assert_nil payment_schedule.stp_setup_intent_id # FIXME
|
||||
assert_empty payment_schedule.payment_gateway_objects
|
||||
assert_nil payment_schedule.wallet_transaction
|
||||
assert_nil payment_schedule.wallet_amount
|
||||
assert_nil payment_schedule.coupon_id
|
||||
|
@ -61,7 +61,7 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
refute invoice.stp_payment_intent_id.blank?
|
||||
refute invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
assert invoice.check_footprint
|
||||
|
||||
@ -177,7 +177,7 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
refute invoice.stp_payment_intent_id.blank?
|
||||
refute invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
assert invoice.check_footprint
|
||||
|
||||
@ -253,7 +253,7 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
refute invoice.stp_payment_intent_id.blank?
|
||||
refute invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
assert invoice.check_footprint
|
||||
|
||||
@ -328,7 +328,7 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
assert invoice.stp_payment_intent_id.blank?
|
||||
assert invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
assert invoice.check_footprint
|
||||
|
||||
@ -367,11 +367,10 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
customer_id: @vlonchamp.id,
|
||||
reservation: {
|
||||
user_id: @vlonchamp.id,
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
card_token: stripe_payment_method,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
@ -407,7 +406,7 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
refute invoice.stp_payment_intent_id.blank?
|
||||
refute invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
assert invoice.check_footprint
|
||||
|
||||
@ -454,7 +453,6 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
plan_id: plan.id,
|
||||
slots_attributes: [
|
||||
{
|
||||
start_at: availability.start_at.to_s(:iso8601),
|
||||
@ -462,6 +460,9 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
availability_id: availability.id
|
||||
}
|
||||
]
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
}
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
@ -490,7 +491,7 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
refute invoice.stp_payment_intent_id.blank?
|
||||
refute invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
assert_equal invoice.total, 2000
|
||||
assert invoice.check_footprint
|
||||
@ -538,7 +539,9 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
end_at: (availability.start_at + 1.hour).to_s(:iso8601),
|
||||
availability_id: availability.id
|
||||
}
|
||||
],
|
||||
]
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id
|
||||
},
|
||||
coupon_code: 'SUNNYFABLAB'
|
||||
@ -568,7 +571,7 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
# invoice assertions
|
||||
invoice = reservation.invoice
|
||||
|
||||
refute invoice.stp_payment_intent_id.blank?
|
||||
refute invoice.payment_gateway_object.blank?
|
||||
refute invoice.total.blank?
|
||||
assert invoice.check_footprint
|
||||
|
||||
@ -595,7 +598,7 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
assert_invoice_pdf invoice
|
||||
|
||||
VCR.use_cassette('reservations_machine_and_plan_using_coupon_retrieve_invoice_from_stripe') do
|
||||
stp_intent = Stripe::PaymentIntent.retrieve(invoice.stp_payment_intent_id, api_key: Setting.get('stripe_secret_key'))
|
||||
stp_intent = invoice.payment_gateway_object.gateway_object.retrieve
|
||||
assert_equal stp_intent.amount, invoice.total
|
||||
end
|
||||
|
||||
@ -620,8 +623,8 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
customer_id: @user_without_subscription.id,
|
||||
reservation: {
|
||||
user_id: @user_without_subscription.id,
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
card_token: stripe_payment_method,
|
||||
@ -696,6 +699,7 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
setup_intent_id: setup_intent[:id],
|
||||
cart_items: {
|
||||
payment_schedule: true,
|
||||
reservation: {
|
||||
reservable_id: training.id,
|
||||
reservable_type: training.class.name,
|
||||
@ -706,8 +710,9 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
availability_id: availability.id
|
||||
}
|
||||
],
|
||||
},
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
payment_schedule: true
|
||||
}
|
||||
}
|
||||
}.to_json, headers: default_headers
|
||||
@ -791,9 +796,11 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
setup_intent_id: setup_intent[:id],
|
||||
cart_items: {
|
||||
coupon_code: 'GIME3EUR',
|
||||
reservation: {
|
||||
payment_schedule: true,
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
payment_schedule: true,
|
||||
},
|
||||
reservation: {
|
||||
reservable_id: machine.id,
|
||||
reservable_type: machine.class.name,
|
||||
slots_attributes: [
|
||||
@ -838,9 +845,9 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
||||
|
||||
# payment schedule assertions
|
||||
assert_not_nil payment_schedule.reference
|
||||
assert_equal 'stripe', payment_schedule.payment_method
|
||||
assert_not_nil payment_schedule.stp_subscription_id
|
||||
assert_not_nil payment_schedule.stp_setup_intent_id # FIXME
|
||||
assert_equal 'card', payment_schedule.payment_method
|
||||
assert_equal 2, payment_schedule.payment_gateway_objects.count
|
||||
assert_not_nil payment_schedule.gateway_payment_mean
|
||||
assert_not_nil payment_schedule.wallet_transaction
|
||||
assert_equal payment_schedule.ordered_items.first.amount, payment_schedule.wallet_amount
|
||||
assert_equal Coupon.find_by(code: 'GIME3EUR').id, payment_schedule.coupon_id
|
||||
|
@ -94,10 +94,10 @@ class Subscriptions::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
params: {
|
||||
setup_intent_id: setup_intent[:id],
|
||||
cart_items: {
|
||||
customer_id: user.id,
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
payment_schedule: true,
|
||||
user_id: user.id,
|
||||
payment_method: 'stripe'
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class Subscriptions::RenewAsAdminTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
@admin = User.find_by(username: 'admin')
|
||||
|
Loading…
x
Reference in New Issue
Block a user