mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-26 20:54:21 +01:00
[WIP] fix tests
This commit is contained in:
parent
336a4b789c
commit
315e899540
@ -99,6 +99,8 @@ class API::StripeController < API::PaymentsController
|
|||||||
if subscription&.status == 'active'
|
if subscription&.status == 'active'
|
||||||
res = on_payment_success(subscription.latest_invoice.payment_intent, cart)
|
res = on_payment_success(subscription.latest_invoice.payment_intent, cart)
|
||||||
render generate_payment_response(subscription.latest_invoice.payment_intent, 'subscription', res)
|
render generate_payment_response(subscription.latest_invoice.payment_intent, 'subscription', res)
|
||||||
|
else
|
||||||
|
render generate_payment_response(subscription.latest_invoice.payment_intent, 'subscription', nil, subscription.id)
|
||||||
end
|
end
|
||||||
rescue Stripe::InvalidRequestError => e
|
rescue Stripe::InvalidRequestError => e
|
||||||
render json: e, status: :unprocessable_entity
|
render json: e, status: :unprocessable_entity
|
||||||
|
@ -26,6 +26,10 @@ interface FreeExtendModalProps {
|
|||||||
* Modal dialog shown to extend the current subscription of a customer, for free
|
* Modal dialog shown to extend the current subscription of a customer, for free
|
||||||
*/
|
*/
|
||||||
const FreeExtendModal: React.FC<FreeExtendModalProps> = ({ isOpen, toggleModal, subscription, customerId, onError, onSuccess }) => {
|
const FreeExtendModal: React.FC<FreeExtendModalProps> = ({ isOpen, toggleModal, subscription, customerId, onError, onSuccess }) => {
|
||||||
|
|
||||||
|
// we do not render the modal if the subscription was not provided
|
||||||
|
if (!subscription) return null;
|
||||||
|
|
||||||
const { t } = useTranslation('admin');
|
const { t } = useTranslation('admin');
|
||||||
|
|
||||||
const [expirationDate, setExpirationDate] = useState<Date>(new Date(subscription.expired_at));
|
const [expirationDate, setExpirationDate] = useState<Date>(new Date(subscription.expired_at));
|
||||||
|
@ -35,6 +35,10 @@ interface RenewModalProps {
|
|||||||
* Modal dialog shown to renew the current subscription of a customer, for free
|
* Modal dialog shown to renew the current subscription of a customer, for free
|
||||||
*/
|
*/
|
||||||
const RenewModal: React.FC<RenewModalProps> = ({ isOpen, toggleModal, subscription, customer, operator, onError, onSuccess }) => {
|
const RenewModal: React.FC<RenewModalProps> = ({ isOpen, toggleModal, subscription, customer, operator, onError, onSuccess }) => {
|
||||||
|
|
||||||
|
// we do not render the modal if the subscription was not provided
|
||||||
|
if (!subscription) return null;
|
||||||
|
|
||||||
const { t } = useTranslation('admin');
|
const { t } = useTranslation('admin');
|
||||||
|
|
||||||
const [expirationDate, setExpirationDate] = useState<Date>(new Date());
|
const [expirationDate, setExpirationDate] = useState<Date>(new Date());
|
||||||
@ -45,8 +49,6 @@ const RenewModal: React.FC<RenewModalProps> = ({ isOpen, toggleModal, subscripti
|
|||||||
|
|
||||||
// on init, we compute the new expiration date
|
// on init, we compute the new expiration date
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!subscription) return;
|
|
||||||
|
|
||||||
setExpirationDate(moment(subscription.expired_at)
|
setExpirationDate(moment(subscription.expired_at)
|
||||||
.add(subscription.plan.interval_count, subscription.plan.interval)
|
.add(subscription.plan.interval_count, subscription.plan.interval)
|
||||||
.toDate());
|
.toDate());
|
||||||
@ -57,13 +59,12 @@ const RenewModal: React.FC<RenewModalProps> = ({ isOpen, toggleModal, subscripti
|
|||||||
|
|
||||||
// when the payment schedule is toggled (requested/ignored), we update the cart accordingly
|
// when the payment schedule is toggled (requested/ignored), we update the cart accordingly
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!subscription) return;
|
|
||||||
|
|
||||||
setCart({
|
setCart({
|
||||||
customer_id: customer.id,
|
customer_id: customer.id,
|
||||||
items: [{
|
items: [{
|
||||||
subscription: {
|
subscription: {
|
||||||
plan_id: subscription.plan.id
|
plan_id: subscription.plan.id,
|
||||||
|
start_at: subscription.expired_at
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
payment_method: PaymentMethod.Other,
|
payment_method: PaymentMethod.Other,
|
||||||
@ -102,9 +103,6 @@ const RenewModal: React.FC<RenewModalProps> = ({ isOpen, toggleModal, subscripti
|
|||||||
setLocalPaymentModal(!localPaymentModal);
|
setLocalPaymentModal(!localPaymentModal);
|
||||||
};
|
};
|
||||||
|
|
||||||
// we do not render the modal if the subscription was not provided
|
|
||||||
if (!subscription) return null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FabModal isOpen={isOpen}
|
<FabModal isOpen={isOpen}
|
||||||
toggleModal={toggleModal}
|
toggleModal={toggleModal}
|
||||||
|
@ -9,7 +9,8 @@ export interface Subscription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SubscriptionRequest {
|
export interface SubscriptionRequest {
|
||||||
plan_id: number
|
plan_id: number,
|
||||||
|
start_at?: Date
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateSubscriptionRequest {
|
export interface UpdateSubscriptionRequest {
|
||||||
|
@ -4,17 +4,19 @@
|
|||||||
class CartItem::PaymentSchedule
|
class CartItem::PaymentSchedule
|
||||||
attr_reader :requested
|
attr_reader :requested
|
||||||
|
|
||||||
def initialize(plan, coupon, requested)
|
def initialize(plan, coupon, requested, customer, start_at = nil)
|
||||||
raise TypeError unless coupon.is_a? CartItem::Coupon
|
raise TypeError unless coupon.is_a? CartItem::Coupon
|
||||||
|
|
||||||
@plan = plan
|
@plan = plan
|
||||||
@coupon = coupon
|
@coupon = coupon
|
||||||
@requested = requested
|
@requested = requested
|
||||||
|
@customer = customer
|
||||||
|
@start_at = start_at
|
||||||
end
|
end
|
||||||
|
|
||||||
def schedule(total, total_without_coupon)
|
def schedule(total, total_without_coupon)
|
||||||
schedule = if @requested && @plan&.monthly_payment
|
schedule = if @requested && @plan&.monthly_payment
|
||||||
PaymentScheduleService.new.compute(@plan, total_without_coupon, coupon: @coupon.coupon)
|
PaymentScheduleService.new.compute(@plan, total_without_coupon, @customer, coupon: @coupon.coupon, start_at: @start_at)
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
# A subscription added to the shopping cart
|
# A subscription added to the shopping cart
|
||||||
class CartItem::Subscription < CartItem::BaseItem
|
class CartItem::Subscription < CartItem::BaseItem
|
||||||
def initialize(plan, customer)
|
attr_reader :start_at
|
||||||
|
|
||||||
|
def initialize(plan, customer, start_at = nil)
|
||||||
raise TypeError unless plan.is_a? Plan
|
raise TypeError unless plan.is_a? Plan
|
||||||
|
|
||||||
@plan = plan
|
@plan = plan
|
||||||
@customer = customer
|
@customer = customer
|
||||||
|
@start_at = start_at
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -30,7 +33,8 @@ class CartItem::Subscription < CartItem::BaseItem
|
|||||||
def to_object
|
def to_object
|
||||||
::Subscription.new(
|
::Subscription.new(
|
||||||
plan_id: @plan.id,
|
plan_id: @plan.id,
|
||||||
statistic_profile_id: StatisticProfile.find_by(user: @customer).id
|
statistic_profile_id: StatisticProfile.find_by(user: @customer).id,
|
||||||
|
start_at: @start_at
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -89,10 +89,10 @@ class ShoppingCart
|
|||||||
PaymentScheduleService.new.create(
|
PaymentScheduleService.new.create(
|
||||||
objects,
|
objects,
|
||||||
price[:before_coupon],
|
price[:before_coupon],
|
||||||
|
@customer,
|
||||||
coupon: @coupon.coupon,
|
coupon: @coupon.coupon,
|
||||||
operator: @operator,
|
operator: @operator,
|
||||||
payment_method: @payment_method,
|
payment_method: @payment_method,
|
||||||
user: @customer,
|
|
||||||
payment_id: payment_id,
|
payment_id: payment_id,
|
||||||
payment_type: payment_type
|
payment_type: payment_type
|
||||||
)
|
)
|
||||||
|
@ -28,7 +28,7 @@ class CartService
|
|||||||
end
|
end
|
||||||
|
|
||||||
coupon = CartItem::Coupon.new(@customer, @operator, cart_items[:coupon_code])
|
coupon = CartItem::Coupon.new(@customer, @operator, cart_items[:coupon_code])
|
||||||
schedule = CartItem::PaymentSchedule.new(plan_info[:plan], coupon, cart_items[:payment_schedule])
|
schedule = CartItem::PaymentSchedule.new(plan_info[:plan], coupon, cart_items[:payment_schedule], @customer, plan_info[:subscription]&.start_at)
|
||||||
|
|
||||||
ShoppingCart.new(
|
ShoppingCart.new(
|
||||||
@customer,
|
@customer,
|
||||||
@ -42,19 +42,22 @@ class CartService
|
|||||||
|
|
||||||
def from_payment_schedule(payment_schedule)
|
def from_payment_schedule(payment_schedule)
|
||||||
@customer = payment_schedule.user
|
@customer = payment_schedule.user
|
||||||
plan = payment_schedule.payment_schedule_objects.find { |pso| pso.object_type == Subscription.name }&.subscription&.plan
|
subscription = payment_schedule.payment_schedule_objects.find { |pso| pso.object_type == Subscription.name }&.subscription
|
||||||
|
plan = subscription&.plan
|
||||||
|
|
||||||
coupon = CartItem::Coupon.new(@customer, @operator, payment_schedule.coupon&.code)
|
coupon = CartItem::Coupon.new(@customer, @operator, payment_schedule.coupon&.code)
|
||||||
schedule = CartItem::PaymentSchedule.new(plan, coupon, true)
|
schedule = CartItem::PaymentSchedule.new(plan, coupon, true, @customer, subscription.start_at)
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
payment_schedule.payment_schedule_objects.each do |object|
|
payment_schedule.payment_schedule_objects.each do |object|
|
||||||
if object.object_type == Subscription.name
|
if object.object_type == Subscription.name
|
||||||
items.push(CartItem::Subscription.new(object.subscription.plan, @customer))
|
items.push(CartItem::Subscription.new(object.subscription.plan, @customer, object.subscription.start_at))
|
||||||
elsif object.object_type == Reservation.name
|
elsif object.object_type == Reservation.name
|
||||||
items.push(reservable_from_payment_schedule_object(object, plan))
|
items.push(reservable_from_payment_schedule_object(object, plan))
|
||||||
elsif object.object_type == PrepaidPack.name
|
elsif object.object_type == PrepaidPack.name
|
||||||
items.push(CartItem::PrepaidPack.new(object.statistic_profile_prepaid_pack.prepaid_pack_id, @customer))
|
items.push(CartItem::PrepaidPack.new(object.statistic_profile_prepaid_pack.prepaid_pack_id, @customer))
|
||||||
|
elsif object.object_type == OfferDay.name
|
||||||
|
items.push(CartItem::FreeExtension.new(@customer, object.offer_day.subscription, object.offer_day.end_date))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -78,7 +81,7 @@ class CartService
|
|||||||
if cart_items[:items][index][:subscription][:plan_id]
|
if cart_items[:items][index][:subscription][:plan_id]
|
||||||
new_plan_being_bought = true
|
new_plan_being_bought = true
|
||||||
plan = Plan.find(cart_items[:items][index][:subscription][:plan_id])
|
plan = Plan.find(cart_items[:items][index][:subscription][:plan_id])
|
||||||
subscription = CartItem::Subscription.new(plan, @customer).to_object
|
subscription = CartItem::Subscription.new(plan, @customer, cart_items[:items][index][:subscription][:start_at]).to_object
|
||||||
plan
|
plan
|
||||||
end
|
end
|
||||||
elsif @customer.subscribed_plan
|
elsif @customer.subscribed_plan
|
||||||
|
@ -6,9 +6,11 @@ class PaymentScheduleService
|
|||||||
# Compute a payment schedule for a new subscription to the provided plan
|
# Compute a payment schedule for a new subscription to the provided plan
|
||||||
# @param plan {Plan}
|
# @param plan {Plan}
|
||||||
# @param total {Number} Total amount of the current shopping cart (which includes this plan) - without coupon
|
# @param total {Number} Total amount of the current shopping cart (which includes this plan) - without coupon
|
||||||
|
# @param customer {User} the customer
|
||||||
# @param coupon {Coupon} apply this coupon, if any
|
# @param coupon {Coupon} apply this coupon, if any
|
||||||
|
# @param start_at {DateTime} schedule the PaymentSchedule to start in the future
|
||||||
##
|
##
|
||||||
def compute(plan, total, coupon: nil)
|
def compute(plan, total, customer, coupon: nil, start_at: nil)
|
||||||
other_items = total - plan.amount
|
other_items = total - plan.amount
|
||||||
# base monthly price of the plan
|
# base monthly price of the plan
|
||||||
price = plan.amount
|
price = plan.amount
|
||||||
@ -22,7 +24,7 @@ class PaymentScheduleService
|
|||||||
end
|
end
|
||||||
items = []
|
items = []
|
||||||
(0..deadlines - 1).each do |i|
|
(0..deadlines - 1).each do |i|
|
||||||
date = DateTime.current + i.months
|
date = (start_at || DateTime.current) + i.months
|
||||||
details = { recurring: per_month }
|
details = { recurring: per_month }
|
||||||
amount = if i.zero?
|
amount = if i.zero?
|
||||||
details[:adjustment] = adjustment.truncate
|
details[:adjustment] = adjustment.truncate
|
||||||
@ -46,14 +48,16 @@ class PaymentScheduleService
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
ps.total = items.map(&:amount).reduce(:+)
|
ps.total = items.map(&:amount).reduce(:+)
|
||||||
|
ps.invoicing_profile = customer.invoicing_profile
|
||||||
|
ps.statistic_profile = customer.statistic_profile
|
||||||
{ payment_schedule: ps, items: items }
|
{ payment_schedule: ps, items: items }
|
||||||
end
|
end
|
||||||
|
|
||||||
def create(objects, total, coupon: nil, operator: nil, payment_method: nil, user: nil,
|
def create(objects, total, customer, coupon: nil, operator: nil, payment_method: nil,
|
||||||
payment_id: nil, payment_type: nil)
|
payment_id: nil, payment_type: nil)
|
||||||
subscription = objects.find { |item| item.class == Subscription }
|
subscription = objects.find { |item| item.class == Subscription }
|
||||||
|
|
||||||
schedule = compute(subscription.plan, total, coupon: coupon)
|
schedule = compute(subscription.plan, total, customer, coupon: coupon, start_at: subscription.start_at)
|
||||||
ps = schedule[:payment_schedule]
|
ps = schedule[:payment_schedule]
|
||||||
items = schedule[:items]
|
items = schedule[:items]
|
||||||
|
|
||||||
@ -68,8 +72,6 @@ class PaymentScheduleService
|
|||||||
ps.payment_gateway_objects.push(pgo)
|
ps.payment_gateway_objects.push(pgo)
|
||||||
end
|
end
|
||||||
ps.operator_profile = operator.invoicing_profile
|
ps.operator_profile = operator.invoicing_profile
|
||||||
ps.invoicing_profile = user.invoicing_profile
|
|
||||||
ps.statistic_profile = user.statistic_profile
|
|
||||||
ps.payment_schedule_items = items
|
ps.payment_schedule_items = items
|
||||||
ps
|
ps
|
||||||
end
|
end
|
||||||
|
@ -9,6 +9,7 @@ class Subscriptions::Subscribe
|
|||||||
@operator_profile_id = operator_profile_id
|
@operator_profile_id = operator_profile_id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO, delete this
|
||||||
def extend_subscription(subscription, new_expiration_date)
|
def extend_subscription(subscription, new_expiration_date)
|
||||||
new_sub = Subscription.create(
|
new_sub = Subscription.create(
|
||||||
plan_id: subscription.plan_id,
|
plan_id: subscription.plan_id,
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# From this migration we save again the start_at field to subscriptions (was removed in 20140703100457_change_start_at_to_expired_at_from_subscription.rb).
|
||||||
|
# This is used to schedule subscriptions start at a future date
|
||||||
|
class AddStartAtAgainToSubscription < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :subscriptions, :start_at, :datetime
|
||||||
|
end
|
||||||
|
end
|
154
db/schema.rb
154
db/schema.rb
@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
ActiveRecord::Schema.define(version: 2021_10_14_135151) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "fuzzystrmatch"
|
enable_extension "fuzzystrmatch"
|
||||||
@ -19,8 +19,8 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
enable_extension "unaccent"
|
enable_extension "unaccent"
|
||||||
|
|
||||||
create_table "abuses", id: :serial, force: :cascade do |t|
|
create_table "abuses", id: :serial, force: :cascade do |t|
|
||||||
t.integer "signaled_id"
|
|
||||||
t.string "signaled_type"
|
t.string "signaled_type"
|
||||||
|
t.integer "signaled_id"
|
||||||
t.string "first_name"
|
t.string "first_name"
|
||||||
t.string "last_name"
|
t.string "last_name"
|
||||||
t.string "email"
|
t.string "email"
|
||||||
@ -49,8 +49,8 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
t.string "locality"
|
t.string "locality"
|
||||||
t.string "country"
|
t.string "country"
|
||||||
t.string "postal_code"
|
t.string "postal_code"
|
||||||
t.integer "placeable_id"
|
|
||||||
t.string "placeable_type"
|
t.string "placeable_type"
|
||||||
|
t.integer "placeable_id"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
end
|
end
|
||||||
@ -64,8 +64,8 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
create_table "assets", id: :serial, force: :cascade do |t|
|
create_table "assets", id: :serial, force: :cascade do |t|
|
||||||
t.integer "viewable_id"
|
|
||||||
t.string "viewable_type"
|
t.string "viewable_type"
|
||||||
|
t.integer "viewable_id"
|
||||||
t.string "attachment"
|
t.string "attachment"
|
||||||
t.string "type"
|
t.string "type"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
@ -133,8 +133,8 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
create_table "credits", id: :serial, force: :cascade do |t|
|
create_table "credits", id: :serial, force: :cascade do |t|
|
||||||
t.integer "creditable_id"
|
|
||||||
t.string "creditable_type"
|
t.string "creditable_type"
|
||||||
|
t.integer "creditable_id"
|
||||||
t.integer "plan_id"
|
t.integer "plan_id"
|
||||||
t.integer "hours"
|
t.integer "hours"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
@ -207,6 +207,14 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
t.index ["user_id"], name: "index_exports_on_user_id"
|
t.index ["user_id"], name: "index_exports_on_user_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "footprint_debugs", force: :cascade do |t|
|
||||||
|
t.string "footprint"
|
||||||
|
t.string "data"
|
||||||
|
t.string "klass"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
end
|
||||||
|
|
||||||
create_table "friendly_id_slugs", id: :serial, force: :cascade do |t|
|
create_table "friendly_id_slugs", id: :serial, force: :cascade do |t|
|
||||||
t.string "slug", null: false
|
t.string "slug", null: false
|
||||||
t.integer "sluggable_id", null: false
|
t.integer "sluggable_id", null: false
|
||||||
@ -274,21 +282,20 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
|
|
||||||
create_table "invoice_items", id: :serial, force: :cascade do |t|
|
create_table "invoice_items", id: :serial, force: :cascade do |t|
|
||||||
t.integer "invoice_id"
|
t.integer "invoice_id"
|
||||||
t.string "stp_invoice_item_id"
|
|
||||||
t.integer "amount"
|
t.integer "amount"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.text "description"
|
t.text "description"
|
||||||
t.integer "subscription_id"
|
|
||||||
t.integer "invoice_item_id"
|
t.integer "invoice_item_id"
|
||||||
t.string "footprint"
|
t.string "footprint"
|
||||||
|
t.string "object_type"
|
||||||
|
t.bigint "object_id"
|
||||||
|
t.boolean "main"
|
||||||
t.index ["invoice_id"], name: "index_invoice_items_on_invoice_id"
|
t.index ["invoice_id"], name: "index_invoice_items_on_invoice_id"
|
||||||
|
t.index ["object_type", "object_id"], name: "index_invoice_items_on_object_type_and_object_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "invoices", id: :serial, force: :cascade do |t|
|
create_table "invoices", id: :serial, force: :cascade do |t|
|
||||||
t.integer "invoiced_id"
|
|
||||||
t.string "invoiced_type"
|
|
||||||
t.string "stp_invoice_id"
|
|
||||||
t.integer "total"
|
t.integer "total"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
@ -307,7 +314,6 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
t.integer "invoicing_profile_id"
|
t.integer "invoicing_profile_id"
|
||||||
t.integer "operator_profile_id"
|
t.integer "operator_profile_id"
|
||||||
t.integer "statistic_profile_id"
|
t.integer "statistic_profile_id"
|
||||||
t.string "stp_payment_intent_id"
|
|
||||||
t.index ["coupon_id"], name: "index_invoices_on_coupon_id"
|
t.index ["coupon_id"], name: "index_invoices_on_coupon_id"
|
||||||
t.index ["invoice_id"], name: "index_invoices_on_invoice_id"
|
t.index ["invoice_id"], name: "index_invoices_on_invoice_id"
|
||||||
t.index ["invoicing_profile_id"], name: "index_invoices_on_invoicing_profile_id"
|
t.index ["invoicing_profile_id"], name: "index_invoices_on_invoicing_profile_id"
|
||||||
@ -350,15 +356,15 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
|
|
||||||
create_table "notifications", id: :serial, force: :cascade do |t|
|
create_table "notifications", id: :serial, force: :cascade do |t|
|
||||||
t.integer "receiver_id"
|
t.integer "receiver_id"
|
||||||
t.integer "attached_object_id"
|
|
||||||
t.string "attached_object_type"
|
t.string "attached_object_type"
|
||||||
|
t.integer "attached_object_id"
|
||||||
t.integer "notification_type_id"
|
t.integer "notification_type_id"
|
||||||
t.boolean "is_read", default: false
|
t.boolean "is_read", default: false
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "receiver_type"
|
t.string "receiver_type"
|
||||||
t.boolean "is_send", default: false
|
t.boolean "is_send", default: false
|
||||||
t.jsonb "meta_data", default: {}
|
t.jsonb "meta_data", default: "{}"
|
||||||
t.index ["notification_type_id"], name: "index_notifications_on_notification_type_id"
|
t.index ["notification_type_id"], name: "index_notifications_on_notification_type_id"
|
||||||
t.index ["receiver_id"], name: "index_notifications_on_receiver_id"
|
t.index ["receiver_id"], name: "index_notifications_on_receiver_id"
|
||||||
end
|
end
|
||||||
@ -421,6 +427,72 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
t.index ["invoicing_profile_id"], name: "index_organizations_on_invoicing_profile_id"
|
t.index ["invoicing_profile_id"], name: "index_organizations_on_invoicing_profile_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "payment_gateway_objects", force: :cascade do |t|
|
||||||
|
t.string "gateway_object_id"
|
||||||
|
t.string "gateway_object_type"
|
||||||
|
t.string "item_type"
|
||||||
|
t.bigint "item_id"
|
||||||
|
t.bigint "payment_gateway_object_id"
|
||||||
|
t.index ["item_type", "item_id"], name: "index_payment_gateway_objects_on_item_type_and_item_id"
|
||||||
|
t.index ["payment_gateway_object_id"], name: "index_payment_gateway_objects_on_payment_gateway_object_id"
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table "payment_schedule_items", force: :cascade do |t|
|
||||||
|
t.integer "amount"
|
||||||
|
t.datetime "due_date"
|
||||||
|
t.string "state", default: "new"
|
||||||
|
t.jsonb "details", default: "{}"
|
||||||
|
t.string "payment_method"
|
||||||
|
t.string "client_secret"
|
||||||
|
t.bigint "payment_schedule_id"
|
||||||
|
t.bigint "invoice_id"
|
||||||
|
t.string "footprint"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["invoice_id"], name: "index_payment_schedule_items_on_invoice_id"
|
||||||
|
t.index ["payment_schedule_id"], name: "index_payment_schedule_items_on_payment_schedule_id"
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table "payment_schedule_objects", force: :cascade do |t|
|
||||||
|
t.string "object_type"
|
||||||
|
t.bigint "object_id"
|
||||||
|
t.bigint "payment_schedule_id"
|
||||||
|
t.boolean "main"
|
||||||
|
t.string "footprint"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["object_type", "object_id"], name: "index_payment_schedule_objects_on_object_type_and_object_id"
|
||||||
|
t.index ["payment_schedule_id"], name: "index_payment_schedule_objects_on_payment_schedule_id"
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table "payment_schedules", force: :cascade do |t|
|
||||||
|
t.integer "total"
|
||||||
|
t.string "reference"
|
||||||
|
t.string "payment_method"
|
||||||
|
t.integer "wallet_amount"
|
||||||
|
t.bigint "wallet_transaction_id"
|
||||||
|
t.bigint "coupon_id"
|
||||||
|
t.string "footprint"
|
||||||
|
t.string "environment"
|
||||||
|
t.bigint "invoicing_profile_id"
|
||||||
|
t.bigint "statistic_profile_id"
|
||||||
|
t.bigint "operator_profile_id"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["coupon_id"], name: "index_payment_schedules_on_coupon_id"
|
||||||
|
t.index ["invoicing_profile_id"], name: "index_payment_schedules_on_invoicing_profile_id"
|
||||||
|
t.index ["operator_profile_id"], name: "index_payment_schedules_on_operator_profile_id"
|
||||||
|
t.index ["statistic_profile_id"], name: "index_payment_schedules_on_statistic_profile_id"
|
||||||
|
t.index ["wallet_transaction_id"], name: "index_payment_schedules_on_wallet_transaction_id"
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table "plan_categories", force: :cascade do |t|
|
||||||
|
t.string "name"
|
||||||
|
t.integer "weight"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
end
|
||||||
|
|
||||||
create_table "plans", id: :serial, force: :cascade do |t|
|
create_table "plans", id: :serial, force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name"
|
||||||
t.integer "amount"
|
t.integer "amount"
|
||||||
@ -438,7 +510,10 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
t.integer "interval_count", default: 1
|
t.integer "interval_count", default: 1
|
||||||
t.string "slug"
|
t.string "slug"
|
||||||
t.boolean "disabled"
|
t.boolean "disabled"
|
||||||
|
t.boolean "monthly_payment"
|
||||||
|
t.bigint "plan_category_id"
|
||||||
t.index ["group_id"], name: "index_plans_on_group_id"
|
t.index ["group_id"], name: "index_plans_on_group_id"
|
||||||
|
t.index ["plan_category_id"], name: "index_plans_on_plan_category_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "plans_availabilities", id: :serial, force: :cascade do |t|
|
create_table "plans_availabilities", id: :serial, force: :cascade do |t|
|
||||||
@ -448,6 +523,21 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
t.index ["plan_id"], name: "index_plans_availabilities_on_plan_id"
|
t.index ["plan_id"], name: "index_plans_availabilities_on_plan_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "prepaid_packs", force: :cascade do |t|
|
||||||
|
t.string "priceable_type"
|
||||||
|
t.bigint "priceable_id"
|
||||||
|
t.bigint "group_id"
|
||||||
|
t.integer "amount"
|
||||||
|
t.integer "minutes"
|
||||||
|
t.string "validity_interval"
|
||||||
|
t.integer "validity_count"
|
||||||
|
t.boolean "disabled"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["group_id"], name: "index_prepaid_packs_on_group_id"
|
||||||
|
t.index ["priceable_type", "priceable_id"], name: "index_prepaid_packs_on_priceable_type_and_priceable_id"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "price_categories", id: :serial, force: :cascade do |t|
|
create_table "price_categories", id: :serial, force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name"
|
||||||
t.text "conditions"
|
t.text "conditions"
|
||||||
@ -458,8 +548,8 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
create_table "prices", id: :serial, force: :cascade do |t|
|
create_table "prices", id: :serial, force: :cascade do |t|
|
||||||
t.integer "group_id"
|
t.integer "group_id"
|
||||||
t.integer "plan_id"
|
t.integer "plan_id"
|
||||||
t.integer "priceable_id"
|
|
||||||
t.string "priceable_type"
|
t.string "priceable_type"
|
||||||
|
t.integer "priceable_id"
|
||||||
t.integer "amount"
|
t.integer "amount"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
@ -531,6 +621,8 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
t.string "slug"
|
t.string "slug"
|
||||||
t.datetime "published_at"
|
t.datetime "published_at"
|
||||||
t.integer "author_statistic_profile_id"
|
t.integer "author_statistic_profile_id"
|
||||||
|
t.tsvector "search_vector"
|
||||||
|
t.index ["search_vector"], name: "projects_search_vector_idx", using: :gin
|
||||||
t.index ["slug"], name: "index_projects_on_slug", unique: true
|
t.index ["slug"], name: "index_projects_on_slug", unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -566,8 +658,8 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
t.text "message"
|
t.text "message"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.integer "reservable_id"
|
|
||||||
t.string "reservable_type"
|
t.string "reservable_type"
|
||||||
|
t.integer "reservable_id"
|
||||||
t.integer "nb_reserve_places"
|
t.integer "nb_reserve_places"
|
||||||
t.integer "statistic_profile_id"
|
t.integer "statistic_profile_id"
|
||||||
t.index ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id"
|
t.index ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id"
|
||||||
@ -576,8 +668,8 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
|
|
||||||
create_table "roles", id: :serial, force: :cascade do |t|
|
create_table "roles", id: :serial, force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name"
|
||||||
t.integer "resource_id"
|
|
||||||
t.string "resource_type"
|
t.string "resource_type"
|
||||||
|
t.integer "resource_id"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id"
|
t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id"
|
||||||
@ -671,6 +763,17 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
t.boolean "ca", default: true
|
t.boolean "ca", default: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "statistic_profile_prepaid_packs", force: :cascade do |t|
|
||||||
|
t.bigint "prepaid_pack_id"
|
||||||
|
t.bigint "statistic_profile_id"
|
||||||
|
t.integer "minutes_used", default: 0
|
||||||
|
t.datetime "expires_at"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["prepaid_pack_id"], name: "index_statistic_profile_prepaid_packs_on_prepaid_pack_id"
|
||||||
|
t.index ["statistic_profile_id"], name: "index_statistic_profile_prepaid_packs_on_statistic_profile_id"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "statistic_profile_trainings", id: :serial, force: :cascade do |t|
|
create_table "statistic_profile_trainings", id: :serial, force: :cascade do |t|
|
||||||
t.integer "statistic_profile_id"
|
t.integer "statistic_profile_id"
|
||||||
t.integer "training_id"
|
t.integer "training_id"
|
||||||
@ -729,12 +832,12 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
|
|
||||||
create_table "subscriptions", id: :serial, force: :cascade do |t|
|
create_table "subscriptions", id: :serial, force: :cascade do |t|
|
||||||
t.integer "plan_id"
|
t.integer "plan_id"
|
||||||
t.string "stp_subscription_id"
|
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.datetime "expiration_date"
|
t.datetime "expiration_date"
|
||||||
t.datetime "canceled_at"
|
t.datetime "canceled_at"
|
||||||
t.integer "statistic_profile_id"
|
t.integer "statistic_profile_id"
|
||||||
|
t.datetime "start_at"
|
||||||
t.index ["plan_id"], name: "index_subscriptions_on_plan_id"
|
t.index ["plan_id"], name: "index_subscriptions_on_plan_id"
|
||||||
t.index ["statistic_profile_id"], name: "index_subscriptions_on_statistic_profile_id"
|
t.index ["statistic_profile_id"], name: "index_subscriptions_on_statistic_profile_id"
|
||||||
end
|
end
|
||||||
@ -827,7 +930,6 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.boolean "is_allow_contact", default: true
|
t.boolean "is_allow_contact", default: true
|
||||||
t.integer "group_id"
|
t.integer "group_id"
|
||||||
t.string "stp_customer_id"
|
|
||||||
t.string "username"
|
t.string "username"
|
||||||
t.string "slug"
|
t.string "slug"
|
||||||
t.boolean "is_active", default: true
|
t.boolean "is_active", default: true
|
||||||
@ -868,15 +970,12 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
|
|
||||||
create_table "wallet_transactions", id: :serial, force: :cascade do |t|
|
create_table "wallet_transactions", id: :serial, force: :cascade do |t|
|
||||||
t.integer "wallet_id"
|
t.integer "wallet_id"
|
||||||
t.integer "transactable_id"
|
|
||||||
t.string "transactable_type"
|
|
||||||
t.string "transaction_type"
|
t.string "transaction_type"
|
||||||
t.integer "amount"
|
t.integer "amount"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.integer "invoicing_profile_id"
|
t.integer "invoicing_profile_id"
|
||||||
t.index ["invoicing_profile_id"], name: "index_wallet_transactions_on_invoicing_profile_id"
|
t.index ["invoicing_profile_id"], name: "index_wallet_transactions_on_invoicing_profile_id"
|
||||||
t.index ["transactable_type", "transactable_id"], name: "index_wallet_transactions_on_transactable"
|
|
||||||
t.index ["wallet_id"], name: "index_wallet_transactions_on_wallet_id"
|
t.index ["wallet_id"], name: "index_wallet_transactions_on_wallet_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -909,6 +1008,17 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
add_foreign_key "o_auth2_mappings", "o_auth2_providers"
|
add_foreign_key "o_auth2_mappings", "o_auth2_providers"
|
||||||
add_foreign_key "open_api_calls_count_tracings", "open_api_clients"
|
add_foreign_key "open_api_calls_count_tracings", "open_api_clients"
|
||||||
add_foreign_key "organizations", "invoicing_profiles"
|
add_foreign_key "organizations", "invoicing_profiles"
|
||||||
|
add_foreign_key "payment_gateway_objects", "payment_gateway_objects"
|
||||||
|
add_foreign_key "payment_schedule_items", "invoices"
|
||||||
|
add_foreign_key "payment_schedule_items", "payment_schedules"
|
||||||
|
add_foreign_key "payment_schedule_objects", "payment_schedules"
|
||||||
|
add_foreign_key "payment_schedules", "coupons"
|
||||||
|
add_foreign_key "payment_schedules", "invoicing_profiles"
|
||||||
|
add_foreign_key "payment_schedules", "invoicing_profiles", column: "operator_profile_id"
|
||||||
|
add_foreign_key "payment_schedules", "statistic_profiles"
|
||||||
|
add_foreign_key "payment_schedules", "wallet_transactions"
|
||||||
|
add_foreign_key "plans", "plan_categories"
|
||||||
|
add_foreign_key "prepaid_packs", "groups"
|
||||||
add_foreign_key "prices", "groups"
|
add_foreign_key "prices", "groups"
|
||||||
add_foreign_key "prices", "plans"
|
add_foreign_key "prices", "plans"
|
||||||
add_foreign_key "project_steps", "projects"
|
add_foreign_key "project_steps", "projects"
|
||||||
@ -929,6 +1039,8 @@ ActiveRecord::Schema.define(version: 2020_06_22_135401) do
|
|||||||
add_foreign_key "spaces_availabilities", "availabilities"
|
add_foreign_key "spaces_availabilities", "availabilities"
|
||||||
add_foreign_key "spaces_availabilities", "spaces"
|
add_foreign_key "spaces_availabilities", "spaces"
|
||||||
add_foreign_key "statistic_custom_aggregations", "statistic_types"
|
add_foreign_key "statistic_custom_aggregations", "statistic_types"
|
||||||
|
add_foreign_key "statistic_profile_prepaid_packs", "prepaid_packs"
|
||||||
|
add_foreign_key "statistic_profile_prepaid_packs", "statistic_profiles"
|
||||||
add_foreign_key "statistic_profile_trainings", "statistic_profiles"
|
add_foreign_key "statistic_profile_trainings", "statistic_profiles"
|
||||||
add_foreign_key "statistic_profile_trainings", "trainings"
|
add_foreign_key "statistic_profile_trainings", "trainings"
|
||||||
add_foreign_key "statistic_profiles", "groups"
|
add_foreign_key "statistic_profiles", "groups"
|
||||||
|
@ -9,20 +9,25 @@ class Integrity::Checksum
|
|||||||
def code
|
def code
|
||||||
dir = Dir.pwd
|
dir = Dir.pwd
|
||||||
|
|
||||||
files = children_files("#{dir}/*")
|
files = if Rails.env.test?
|
||||||
.concat(children_files("#{dir}/app/**/*"))
|
# in test mode, we compute a "lite" checksum to speed-up test running time
|
||||||
.concat(children_files("#{dir}/bin/**/*"))
|
children_files("#{dir}/*")
|
||||||
.concat(children_files("#{dir}/config/**/*"))
|
else
|
||||||
.concat(children_files("#{dir}/db/**/*"))
|
children_files("#{dir}/*")
|
||||||
.concat(children_files("#{dir}/doc/**/*"))
|
.concat(children_files("#{dir}/app/**/*"))
|
||||||
.concat(children_files("#{dir}/docker/**/*"))
|
.concat(children_files("#{dir}/bin/**/*"))
|
||||||
.concat(children_files("#{dir}/lib/**/*"))
|
.concat(children_files("#{dir}/config/**/*"))
|
||||||
.concat(children_files("#{dir}/node_modules/**/*"))
|
.concat(children_files("#{dir}/db/**/*"))
|
||||||
.concat(children_files("#{dir}/plugins/**/*"))
|
.concat(children_files("#{dir}/doc/**/*"))
|
||||||
.concat(children_files("#{dir}/provision/**/*"))
|
.concat(children_files("#{dir}/docker/**/*"))
|
||||||
.concat(children_files("#{dir}/scripts/**/*"))
|
.concat(children_files("#{dir}/lib/**/*"))
|
||||||
.concat(children_files("#{dir}/test/**/*"))
|
.concat(children_files("#{dir}/node_modules/**/*"))
|
||||||
.concat(children_files("#{dir}/vendor/**/*"))
|
.concat(children_files("#{dir}/plugins/**/*"))
|
||||||
|
.concat(children_files("#{dir}/provision/**/*"))
|
||||||
|
.concat(children_files("#{dir}/scripts/**/*"))
|
||||||
|
.concat(children_files("#{dir}/test/**/*"))
|
||||||
|
.concat(children_files("#{dir}/vendor/**/*"))
|
||||||
|
end
|
||||||
|
|
||||||
content = files.map { |f| File.read(f) }.join
|
content = files.map { |f| File.read(f) }.join
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@ class Stripe::Service < Payment::Service
|
|||||||
payment_schedule.payment_schedule_items = price_details[:schedule][:items]
|
payment_schedule.payment_schedule_items = price_details[:schedule][:items]
|
||||||
first_item = price_details[:schedule][:items].min_by(&:due_date)
|
first_item = price_details[:schedule][:items].min_by(&:due_date)
|
||||||
subscription = shopping_cart.items.find { |item| item.class == CartItem::Subscription }
|
subscription = shopping_cart.items.find { |item| item.class == CartItem::Subscription }
|
||||||
reservable_stp_id = shopping_cart.items.find { |item| item.is_a?(CartItem::Reservation) }.to_object
|
reservable_stp_id = shopping_cart.items.find { |item| item.is_a?(CartItem::Reservation) }&.to_object
|
||||||
.reservable&.payment_gateway_object&.gateway_object_id
|
&.reservable&.payment_gateway_object&.gateway_object_id
|
||||||
|
|
||||||
WalletService.debit_user_wallet(payment_schedule, shopping_cart.customer, transaction: false)
|
WalletService.debit_user_wallet(payment_schedule, shopping_cart.customer, transaction: false)
|
||||||
handle_wallet_transaction(payment_schedule)
|
handle_wallet_transaction(payment_schedule)
|
||||||
@ -29,17 +29,25 @@ class Stripe::Service < Payment::Service
|
|||||||
|
|
||||||
|
|
||||||
stripe_key = Setting.get('stripe_secret_key')
|
stripe_key = Setting.get('stripe_secret_key')
|
||||||
Stripe::Subscription.create({
|
stp_subscription = Stripe::Subscription.create({
|
||||||
customer: shopping_cart.customer.payment_gateway_object.gateway_object_id,
|
customer: shopping_cart.customer.payment_gateway_object.gateway_object_id,
|
||||||
cancel_at: (payment_schedule.payment_schedule_items.max_by(&:due_date).due_date + 1.month).to_i,
|
cancel_at: (payment_schedule.payment_schedule_items.max_by(&:due_date).due_date + 1.month).to_i,
|
||||||
add_invoice_items: items,
|
add_invoice_items: items,
|
||||||
coupon: payment_schedule.coupon&.code,
|
coupon: payment_schedule.coupon&.code,
|
||||||
items: [
|
items: [
|
||||||
{ price: price[:id] }
|
{ price: price[:id] }
|
||||||
],
|
],
|
||||||
default_payment_method: payment_method_id,
|
default_payment_method: payment_method_id,
|
||||||
expand: %w[latest_invoice.payment_intent]
|
expand: %w[latest_invoice.payment_intent]
|
||||||
}, { api_key: stripe_key })
|
}, { api_key: stripe_key })
|
||||||
|
return stp_subscription unless subscription.start_at
|
||||||
|
|
||||||
|
Stripe::SubscriptionSchedule.create({
|
||||||
|
from_subscription: stp_subscription.id,
|
||||||
|
start_date: subscription.start_at
|
||||||
|
}, { api_key: stripe_key })
|
||||||
|
|
||||||
|
stp_subscription
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_subscription(payment_schedule, payment_intent_id)
|
def create_subscription(payment_schedule, payment_intent_id)
|
||||||
|
@ -705,36 +705,10 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
|||||||
plan = Plan.find_by(group_id: @user_without_subscription.group.id, type: 'Plan', base_name: 'Abonnement mensualisable')
|
plan = Plan.find_by(group_id: @user_without_subscription.group.id, type: 'Plan', base_name: 'Abonnement mensualisable')
|
||||||
|
|
||||||
VCR.use_cassette('reservations_training_subscription_with_payment_schedule') do
|
VCR.use_cassette('reservations_training_subscription_with_payment_schedule') do
|
||||||
post '/api/stripe/payment_schedule',
|
post '/api/stripe/setup_subscription',
|
||||||
params: {
|
params: {
|
||||||
payment_method_id: stripe_payment_method,
|
payment_method_id: stripe_payment_method,
|
||||||
cart_items: {
|
cart_items: {
|
||||||
items: [
|
|
||||||
{
|
|
||||||
subscription: {
|
|
||||||
plan_id: plan.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
payment_schedule: true,
|
|
||||||
payment_method: 'cart'
|
|
||||||
}
|
|
||||||
}.to_json, headers: default_headers
|
|
||||||
|
|
||||||
# Check response format & status
|
|
||||||
assert_equal 200, response.status, response.body
|
|
||||||
assert_equal Mime[:json], response.content_type
|
|
||||||
|
|
||||||
# Check the response
|
|
||||||
sub = json_response(response.body)
|
|
||||||
assert_not_nil sub[:id]
|
|
||||||
|
|
||||||
post '/api/stripe/confirm_payment_schedule',
|
|
||||||
params: {
|
|
||||||
subscription_id: sub[:id],
|
|
||||||
cart_items: {
|
|
||||||
payment_schedule: true,
|
|
||||||
payment_method: 'card',
|
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
reservation: {
|
reservation: {
|
||||||
@ -754,9 +728,19 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
|||||||
plan_id: plan.id
|
plan_id: plan.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
payment_schedule: true,
|
||||||
|
payment_method: 'cart'
|
||||||
}
|
}
|
||||||
}.to_json, headers: default_headers
|
}.to_json, headers: default_headers
|
||||||
|
|
||||||
|
# Check response format & status
|
||||||
|
assert_equal 201, response.status, response.body
|
||||||
|
assert_equal Mime[:json], response.content_type
|
||||||
|
|
||||||
|
# Check the response
|
||||||
|
sub = json_response(response.body)
|
||||||
|
assert_not_nil sub[:id]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check response format & status
|
# Check response format & status
|
||||||
@ -809,37 +793,10 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
|||||||
plan = Plan.find_by(group_id: user.group.id, type: 'Plan', base_name: 'Abonnement mensualisable')
|
plan = Plan.find_by(group_id: user.group.id, type: 'Plan', base_name: 'Abonnement mensualisable')
|
||||||
|
|
||||||
VCR.use_cassette('reservations_machine_subscription_with_payment_schedule_coupon_wallet') do
|
VCR.use_cassette('reservations_machine_subscription_with_payment_schedule_coupon_wallet') do
|
||||||
post '/api/stripe/payment_schedule',
|
post '/api/stripe/setup_subscription',
|
||||||
params: {
|
params: {
|
||||||
payment_method_id: stripe_payment_method,
|
payment_method_id: stripe_payment_method,
|
||||||
cart_items: {
|
cart_items: {
|
||||||
items: [
|
|
||||||
{
|
|
||||||
subscription: {
|
|
||||||
plan_id: plan.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
payment_schedule: true,
|
|
||||||
payment_method: 'cart'
|
|
||||||
}
|
|
||||||
}.to_json, headers: default_headers
|
|
||||||
|
|
||||||
# Check response format & status
|
|
||||||
assert_equal 200, response.status, response.body
|
|
||||||
assert_equal Mime[:json], response.content_type
|
|
||||||
|
|
||||||
# Check the response
|
|
||||||
res = json_response(response.body)
|
|
||||||
assert_not_nil res[:id]
|
|
||||||
|
|
||||||
post '/api/stripe/confirm_payment_schedule',
|
|
||||||
params: {
|
|
||||||
subscription_id: res[:id],
|
|
||||||
cart_items: {
|
|
||||||
coupon_code: 'GIME3EUR',
|
|
||||||
payment_schedule: true,
|
|
||||||
payment_method: 'card',
|
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
reservation: {
|
reservation: {
|
||||||
@ -859,9 +816,19 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
|||||||
plan_id: plan.id
|
plan_id: plan.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
payment_schedule: true,
|
||||||
|
payment_method: 'cart'
|
||||||
}
|
}
|
||||||
}.to_json, headers: default_headers
|
}.to_json, headers: default_headers
|
||||||
|
|
||||||
|
# Check response format & status
|
||||||
|
assert_equal 201, response.status, response.body
|
||||||
|
assert_equal Mime[:json], response.content_type
|
||||||
|
|
||||||
|
# Check the response
|
||||||
|
res = json_response(response.body)
|
||||||
|
assert_not_nil res[:id]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check response format & status
|
# Check response format & status
|
||||||
@ -896,7 +863,7 @@ class Reservations::CreateTest < ActionDispatch::IntegrationTest
|
|||||||
assert_not_nil payment_schedule.reference
|
assert_not_nil payment_schedule.reference
|
||||||
assert_equal 'card', payment_schedule.payment_method
|
assert_equal 'card', payment_schedule.payment_method
|
||||||
assert_equal 2, payment_schedule.payment_gateway_objects.count
|
assert_equal 2, payment_schedule.payment_gateway_objects.count
|
||||||
#assert_not_nil payment_schedule.gateway_payment_mean
|
assert_not_nil payment_schedule.gateway_payment_mean
|
||||||
assert_not_nil payment_schedule.wallet_transaction
|
assert_not_nil payment_schedule.wallet_transaction
|
||||||
assert_equal payment_schedule.ordered_items.first.amount, payment_schedule.wallet_amount
|
assert_equal payment_schedule.ordered_items.first.amount, payment_schedule.wallet_amount
|
||||||
assert_equal Coupon.find_by(code: 'GIME3EUR').id, payment_schedule.coupon_id
|
assert_equal Coupon.find_by(code: 'GIME3EUR').id, payment_schedule.coupon_id
|
||||||
|
@ -77,7 +77,7 @@ class Subscriptions::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
|||||||
payment_schedule_items_count = PaymentScheduleItem.count
|
payment_schedule_items_count = PaymentScheduleItem.count
|
||||||
|
|
||||||
VCR.use_cassette('subscriptions_admin_create_with_payment_schedule') do
|
VCR.use_cassette('subscriptions_admin_create_with_payment_schedule') do
|
||||||
post '/api/stripe/payment_schedule',
|
post '/api/stripe/setup_subscription',
|
||||||
params: {
|
params: {
|
||||||
payment_method_id: stripe_payment_method,
|
payment_method_id: stripe_payment_method,
|
||||||
cart_items: {
|
cart_items: {
|
||||||
@ -95,34 +95,15 @@ class Subscriptions::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
|||||||
}.to_json, headers: default_headers
|
}.to_json, headers: default_headers
|
||||||
|
|
||||||
# Check response format & status
|
# Check response format & status
|
||||||
assert_equal 200, response.status, response.body
|
assert_equal 201, response.status, response.body
|
||||||
assert_equal Mime[:json], response.content_type
|
assert_equal Mime[:json], response.content_type
|
||||||
|
|
||||||
# Check the response
|
# Check the response
|
||||||
res = json_response(response.body)
|
res = json_response(response.body)
|
||||||
assert_not_nil res[:id]
|
assert_not_nil res[:id]
|
||||||
|
|
||||||
post '/api/stripe/confirm_payment_schedule',
|
|
||||||
params: {
|
|
||||||
subscription_id: res[:id],
|
|
||||||
cart_items: {
|
|
||||||
customer_id: user.id,
|
|
||||||
payment_schedule: true,
|
|
||||||
payment_method: 'card',
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
subscription: {
|
|
||||||
plan_id: plan.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}.to_json, headers: default_headers
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check generalities
|
# Check generalities
|
||||||
assert_equal 201, response.status, response.body
|
|
||||||
assert_equal Mime[:json], response.content_type
|
|
||||||
assert_equal invoice_count, Invoice.count, "an invoice was generated but it shouldn't"
|
assert_equal invoice_count, Invoice.count, "an invoice was generated but it shouldn't"
|
||||||
assert_equal payment_schedule_count + 1, PaymentSchedule.count, 'missing the payment schedule'
|
assert_equal payment_schedule_count + 1, PaymentSchedule.count, 'missing the payment schedule'
|
||||||
assert_equal payment_schedule_items_count + 12, PaymentScheduleItem.count, 'missing some payment schedule items'
|
assert_equal payment_schedule_items_count + 12, PaymentScheduleItem.count, 'missing some payment schedule items'
|
||||||
|
@ -195,7 +195,7 @@ class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest
|
|||||||
payment_schedule_items_count = PaymentScheduleItem.count
|
payment_schedule_items_count = PaymentScheduleItem.count
|
||||||
|
|
||||||
VCR.use_cassette('subscriptions_user_create_with_payment_schedule') do
|
VCR.use_cassette('subscriptions_user_create_with_payment_schedule') do
|
||||||
post '/api/stripe/payment_schedule',
|
post '/api/stripe/setup_subscription',
|
||||||
params: {
|
params: {
|
||||||
payment_method_id: stripe_payment_method,
|
payment_method_id: stripe_payment_method,
|
||||||
cart_items: {
|
cart_items: {
|
||||||
@ -211,18 +211,68 @@ class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest
|
|||||||
}
|
}
|
||||||
}.to_json, headers: default_headers
|
}.to_json, headers: default_headers
|
||||||
|
|
||||||
|
# Check response format & status
|
||||||
|
assert_equal 201, response.status, response.body
|
||||||
|
assert_equal Mime[:json], response.content_type
|
||||||
|
|
||||||
|
# Check the response
|
||||||
|
sub = json_response(response.body)
|
||||||
|
assert_not_nil sub[:id]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Check generalities
|
||||||
|
assert_equal payment_schedule_count + 1, PaymentSchedule.count, 'missing the payment schedule'
|
||||||
|
assert_equal payment_schedule_items_count + 12, PaymentScheduleItem.count, 'missing some payment schedule items'
|
||||||
|
|
||||||
|
# Check the correct plan was subscribed
|
||||||
|
result = json_response(response.body)
|
||||||
|
assert_equal PaymentSchedule.last.id, result[:id], 'payment schedule id does not match'
|
||||||
|
subscription = PaymentSchedule.find(result[:id]).payment_schedule_objects.first.object
|
||||||
|
assert_equal plan.id, subscription.plan_id, 'subscribed plan does not match'
|
||||||
|
|
||||||
|
# Check that the user has the correct subscription
|
||||||
|
assert_not_nil @user.subscription, "user's subscription was not found"
|
||||||
|
assert_not_nil @user.subscription.plan, "user's subscribed plan was not found"
|
||||||
|
assert_equal plan.id, @user.subscription.plan_id, "user's plan does not match"
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'user takes a subscription but does not confirm 3DS' do
|
||||||
|
plan = Plan.find_by(group_id: @user.group.id, type: 'Plan', base_name: 'Abonnement mensualisable')
|
||||||
|
payment_schedule_count = PaymentSchedule.count
|
||||||
|
payment_schedule_items_count = PaymentScheduleItem.count
|
||||||
|
|
||||||
|
VCR.use_cassette('subscriptions_user_create_without_3ds_confirmation') do
|
||||||
|
post '/api/stripe/setup_subscription',
|
||||||
|
params: {
|
||||||
|
payment_method_id: stripe_payment_method(error: :require_3ds),
|
||||||
|
cart_items: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
subscription: {
|
||||||
|
plan_id: plan.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
payment_schedule: true,
|
||||||
|
payment_method: 'cart'
|
||||||
|
}
|
||||||
|
}.to_json, headers: default_headers
|
||||||
|
|
||||||
# Check response format & status
|
# Check response format & status
|
||||||
assert_equal 200, response.status, response.body
|
assert_equal 200, response.status, response.body
|
||||||
assert_equal Mime[:json], response.content_type
|
assert_equal Mime[:json], response.content_type
|
||||||
|
|
||||||
# Check the response
|
# Check the response
|
||||||
sub = json_response(response.body)
|
res = json_response(response.body)
|
||||||
assert_not_nil sub[:id]
|
assert res[:requires_action]
|
||||||
|
assert_not_nil res[:payment_intent_client_secret]
|
||||||
|
assert_not_nil res[:subscription_id]
|
||||||
|
assert_equal 'subscription', res[:type]
|
||||||
|
|
||||||
# create the subscription
|
# try to confirm the subscription
|
||||||
post '/api/stripe/confirm_payment_schedule',
|
post '/api/stripe/confirm_subscription',
|
||||||
params: {
|
params: {
|
||||||
subscription_id: sub[:id],
|
subscription_id: res[:subscription_id],
|
||||||
cart_items: {
|
cart_items: {
|
||||||
payment_schedule: true,
|
payment_schedule: true,
|
||||||
payment_method: 'card',
|
payment_method: 'card',
|
||||||
@ -238,20 +288,19 @@ class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Check generalities
|
# Check generalities
|
||||||
assert_equal 201, response.status, response.body
|
assert_equal 200, response.status, response.body
|
||||||
assert_equal Mime[:json], response.content_type
|
assert_equal Mime[:json], response.content_type
|
||||||
assert_equal payment_schedule_count + 1, PaymentSchedule.count, 'missing the payment schedule'
|
|
||||||
assert_equal payment_schedule_items_count + 12, PaymentScheduleItem.count, 'missing some payment schedule items'
|
|
||||||
|
|
||||||
# Check the correct plan was subscribed
|
res = json_response(response.body)
|
||||||
result = json_response(response.body)
|
assert res[:requires_action]
|
||||||
assert_equal PaymentSchedule.last.id, result[:id], 'payment schedule id does not match'
|
assert_not_nil res[:payment_intent_client_secret]
|
||||||
subscription = PaymentSchedule.find(result[:id]).payment_schedule_objects.first.object
|
assert_not_nil res[:subscription_id]
|
||||||
assert_equal plan.id, subscription.plan_id, 'subscribed plan does not match'
|
assert_equal 'subscription', res[:type]
|
||||||
|
|
||||||
# Check that the user has the correct subscription
|
assert_equal payment_schedule_count, PaymentSchedule.count, 'the payment schedule was created anyway'
|
||||||
assert_not_nil @user.subscription, "user's subscription was not found"
|
assert_equal payment_schedule_items_count, PaymentScheduleItem.count, 'some payment schedule items were created anyway'
|
||||||
assert_not_nil @user.subscription.plan, "user's subscribed plan was not found"
|
|
||||||
assert_equal plan.id, @user.subscription.plan_id, "user's plan does not match"
|
# Check that the user has no subscription
|
||||||
|
assert_nil @user.subscription, "user's subscription was not found"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -57,6 +57,8 @@ class ActiveSupport::TestCase
|
|||||||
exp_year = 1964
|
exp_year = 1964
|
||||||
when /invalid_cvc/
|
when /invalid_cvc/
|
||||||
cvc = '99'
|
cvc = '99'
|
||||||
|
when /require_3ds/
|
||||||
|
number = '4000002760003184'
|
||||||
end
|
end
|
||||||
|
|
||||||
Stripe::PaymentMethod.create(
|
Stripe::PaymentMethod.create(
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user