mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-19 13:54:25 +01:00
refactoring of reservation:pay_and_save
TODO: debug with tests, refactor subscription:pay_and_save on the same template
This commit is contained in:
parent
6c8d65fba1
commit
40c78974b8
@ -106,7 +106,8 @@ class API::PaymentsController < API::ApiController
|
||||
.pay_and_save(@reservation,
|
||||
payment_details: details,
|
||||
payment_intent_id: intent.id,
|
||||
schedule: params[:cart_items][:reservation][:payment_schedule])
|
||||
schedule: params[:cart_items][:reservation][:payment_schedule],
|
||||
payment_method: params[:cart_items][:reservation][:payment_method])
|
||||
if intent.class == Stripe::PaymentIntent
|
||||
Stripe::PaymentIntent.update(
|
||||
intent.id,
|
||||
|
@ -37,7 +37,8 @@ class API::ReservationsController < API::ApiController
|
||||
is_reserve = Reservations::Reserve.new(user_id, current_user.invoicing_profile.id)
|
||||
.pay_and_save(@reservation,
|
||||
payment_details: price[:price_details],
|
||||
schedule: params[:reservation][:payment_schedule])
|
||||
schedule: params[:reservation][:payment_schedule],
|
||||
payment_method: params[:reservation][:payment_method])
|
||||
|
||||
if is_reserve
|
||||
SubscriptionExtensionAfterReservation.new(@reservation).extend_subscription_if_eligible
|
||||
|
@ -33,6 +33,13 @@ class PaymentSchedule < ApplicationRecord
|
||||
save
|
||||
end
|
||||
|
||||
def set_wallet_transaction(amount, transaction_id)
|
||||
raise InvalidFootprintError unless check_footprint
|
||||
|
||||
update_columns(wallet_amount: amount, wallet_transaction_id: transaction_id)
|
||||
chain_record
|
||||
end
|
||||
|
||||
def chain_record
|
||||
self.footprint = compute_footprint
|
||||
save!
|
||||
@ -46,4 +53,8 @@ class PaymentSchedule < ApplicationRecord
|
||||
def compute_footprint
|
||||
FootprintService.compute_footprint(PaymentSchedule, self)
|
||||
end
|
||||
|
||||
def check_footprint
|
||||
payment_schedule_items.map(&:check_footprint).all? && footprint == compute_footprint
|
||||
end
|
||||
end
|
||||
|
@ -4,4 +4,23 @@
|
||||
class PaymentScheduleItem < ApplicationRecord
|
||||
belongs_to :payment_schedule
|
||||
belongs_to :invoice
|
||||
after_create :chain_record
|
||||
|
||||
def chain_record
|
||||
self.footprint = compute_footprint
|
||||
save!
|
||||
FootprintDebug.create!(
|
||||
footprint: footprint,
|
||||
data: FootprintService.footprint_data(PaymentScheduleItem, self),
|
||||
klass: PaymentScheduleItem.name
|
||||
)
|
||||
end
|
||||
|
||||
def check_footprint
|
||||
footprint == compute_footprint
|
||||
end
|
||||
|
||||
def compute_footprint
|
||||
FootprintService.compute_footprint(PaymentScheduleItem, self)
|
||||
end
|
||||
end
|
||||
|
@ -30,133 +30,33 @@ class Reservation < ApplicationRecord
|
||||
after_commit :notify_member_create_reservation, on: :create
|
||||
after_commit :notify_admin_member_create_reservation, on: :create
|
||||
after_save :update_event_nb_free_places, if: proc { |reservation| reservation.reservable_type == 'Event' }
|
||||
after_create :debit_user_wallet
|
||||
|
||||
##
|
||||
# Generate an array of {Stripe::InvoiceItem} with the elements in the current reservation, price included.
|
||||
# @param payment_details {Hash} as generated by Price.compute
|
||||
# These checks will run before the invoice/payment-schedule is generated
|
||||
##
|
||||
def generate_invoice_items(payment_details = nil)
|
||||
def pre_check
|
||||
# check that none of the reserved availabilities was locked
|
||||
slots.each do |slot|
|
||||
raise LockedError if slot.availability.lock
|
||||
end
|
||||
|
||||
case reservable
|
||||
# === Event reservation ===
|
||||
when Event
|
||||
slots.each do |slot|
|
||||
description = "#{reservable.name}\n"
|
||||
description += if slot.start_at.to_date != slot.end_at.to_date
|
||||
I18n.t('events.from_STARTDATE_to_ENDDATE',
|
||||
STARTDATE: I18n.l(slot.start_at.to_date, format: :long),
|
||||
ENDDATE: I18n.l(slot.end_at.to_date, format: :long)) + ' ' +
|
||||
I18n.t('events.from_STARTTIME_to_ENDTIME',
|
||||
STARTTIME: I18n.l(slot.start_at, format: :hour_minute),
|
||||
ENDTIME: I18n.l(slot.end_at, format: :hour_minute))
|
||||
else
|
||||
"#{I18n.l slot.start_at.to_date, format: :long} #{I18n.l slot.start_at, format: :hour_minute}" \
|
||||
" - #{I18n.l slot.end_at, format: :hour_minute}"
|
||||
end
|
||||
|
||||
price_slot = payment_details[:elements][:slots].detect { |p_slot| p_slot[:start_at].to_time.in_time_zone == slot[:start_at] }
|
||||
invoice.invoice_items.push InvoiceItem.new(
|
||||
amount: price_slot[:price],
|
||||
description: description
|
||||
)
|
||||
end
|
||||
# === Space|Machine|Training reservation ===
|
||||
else
|
||||
slots.each do |slot|
|
||||
description = reservable.name +
|
||||
" #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}"
|
||||
|
||||
price_slot = payment_details[:elements][:slots].detect { |p_slot| p_slot[:start_at].to_time.in_time_zone == slot[:start_at] }
|
||||
invoice.invoice_items.push InvoiceItem.new(
|
||||
amount: price_slot[:price],
|
||||
description: description
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# === Coupon ===
|
||||
@coupon = payment_details[:coupon]
|
||||
|
||||
# === Wallet ===
|
||||
@wallet_amount_debit = wallet_amount_debit
|
||||
end
|
||||
|
||||
# check reservation amount total and strip invoice total to pay is equal
|
||||
# @param stp_invoice[Stripe::Invoice]
|
||||
# @param coupon_code[String]
|
||||
# return Boolean
|
||||
def is_equal_reservation_total_and_stp_invoice_total(stp_invoice, coupon_code = nil)
|
||||
compute_amount_total_to_pay(coupon_code) == stp_invoice.total
|
||||
## Generate the subscription associated with for the current reservation
|
||||
def generate_subscription
|
||||
return unless plan_id
|
||||
|
||||
self.subscription = Subscription.find_or_initialize_by(statistic_profile_id: statistic_profile_id)
|
||||
subscription.attributes = { plan_id: plan_id, statistic_profile_id: statistic_profile_id, expiration_date: nil }
|
||||
|
||||
subscription.init_save
|
||||
subscription
|
||||
end
|
||||
|
||||
def clear_payment_info(card, invoice)
|
||||
card&.delete
|
||||
if invoice
|
||||
invoice.closed = true
|
||||
invoice.save
|
||||
end
|
||||
rescue Stripe::InvalidRequestError => e
|
||||
logger.error e
|
||||
rescue Stripe::AuthenticationError => e
|
||||
logger.error e
|
||||
rescue Stripe::APIConnectionError => e
|
||||
logger.error e
|
||||
rescue Stripe::StripeError => e
|
||||
logger.error e
|
||||
rescue StandardError => e
|
||||
logger.error e
|
||||
end
|
||||
|
||||
def clean_pending_strip_invoice_items
|
||||
pending_invoice_items = Stripe::InvoiceItem.list(
|
||||
{ customer: user.stp_customer_id, limit: 100 },
|
||||
{ api_key: Setting.get('stripe_secret_key') }
|
||||
).data.select { |ii| ii.invoice.nil? }
|
||||
pending_invoice_items.each(&:delete)
|
||||
end
|
||||
|
||||
def save_with_payment(operator_profile_id, payment_details, payment_intent_id = nil, schedule: false)
|
||||
operator = InvoicingProfile.find(operator_profile_id)&.user
|
||||
method = operator&.admin? || (operator&.manager? && operator != user) ? nil : 'stripe'
|
||||
|
||||
build_invoice(
|
||||
invoicing_profile: user.invoicing_profile,
|
||||
statistic_profile: user.statistic_profile,
|
||||
operator_profile_id: operator_profile_id,
|
||||
stp_payment_intent_id: payment_intent_id,
|
||||
payment_method: method
|
||||
)
|
||||
generate_invoice_items(payment_details)
|
||||
|
||||
return false unless valid?
|
||||
|
||||
if plan_id
|
||||
self.subscription = Subscription.find_or_initialize_by(statistic_profile_id: statistic_profile_id)
|
||||
subscription.attributes = { plan_id: plan_id, statistic_profile_id: statistic_profile_id, expiration_date: nil }
|
||||
if subscription.save_with_payment(operator_profile_id, invoice: false, schedule: schedule)
|
||||
invoice.invoice_items.push InvoiceItem.new(
|
||||
amount: payment_details[:elements][:plan],
|
||||
description: subscription.plan.name,
|
||||
subscription_id: subscription.id
|
||||
)
|
||||
set_total_and_coupon(payment_details[:coupon])
|
||||
save!
|
||||
else
|
||||
errors[:card] << subscription.errors[:card].join
|
||||
return false
|
||||
end
|
||||
else
|
||||
set_total_and_coupon(payment_details[:coupon])
|
||||
save!
|
||||
end
|
||||
|
||||
##
|
||||
# These actions will be realized after the reservation is initially saved (on creation)
|
||||
##
|
||||
def post_save
|
||||
UsersCredits::Manager.new(reservation: self).update_credits
|
||||
true
|
||||
end
|
||||
|
||||
# @param canceled if true, count the number of seats for this reservation, including canceled seats
|
||||
@ -219,61 +119,4 @@ class Reservation < ApplicationRecord
|
||||
receiver: User.admins_and_managers,
|
||||
attached_object: self
|
||||
end
|
||||
|
||||
def cart_total
|
||||
total = (invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+) or 0)
|
||||
if plan_id.present?
|
||||
plan = Plan.find(plan_id)
|
||||
total += plan.amount
|
||||
end
|
||||
total
|
||||
end
|
||||
|
||||
def wallet_amount_debit
|
||||
total = cart_total
|
||||
total = CouponService.new.apply(total, @coupon, user.id) if @coupon
|
||||
|
||||
wallet_amount = (user.wallet.amount * 100).to_i
|
||||
|
||||
wallet_amount >= total ? total : wallet_amount
|
||||
end
|
||||
|
||||
def debit_user_wallet
|
||||
return unless @wallet_amount_debit.present? && @wallet_amount_debit != 0
|
||||
|
||||
amount = @wallet_amount_debit / 100.0
|
||||
wallet_transaction = WalletService.new(user: user, wallet: user.wallet).debit(amount, self)
|
||||
# wallet debit success
|
||||
raise DebitWalletError unless wallet_transaction
|
||||
|
||||
invoice.set_wallet_transaction(@wallet_amount_debit, wallet_transaction.id)
|
||||
end
|
||||
|
||||
# this function only use for compute total of reservation before save
|
||||
def compute_amount_total_to_pay(coupon_code = nil)
|
||||
total = invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+)
|
||||
unless coupon_code.nil?
|
||||
cp = Coupon.find_by(code: coupon_code)
|
||||
raise InvalidCouponError unless !cp.nil? && cp.status(user.id) == 'active'
|
||||
|
||||
total = CouponService.new.apply(total, cp, user.id)
|
||||
end
|
||||
total - wallet_amount_debit
|
||||
end
|
||||
|
||||
##
|
||||
# Set the total price to the reservation's invoice, summing its whole items.
|
||||
# Additionally a coupon may be applied to this invoice to make a discount on the total price
|
||||
# @param [coupon] {Coupon} optional coupon to apply to the invoice
|
||||
##
|
||||
def set_total_and_coupon(coupon = nil)
|
||||
total = invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+)
|
||||
|
||||
unless coupon.nil?
|
||||
total = CouponService.new.apply(total, coupon, user.id)
|
||||
invoice.coupon_id = coupon.id
|
||||
end
|
||||
|
||||
invoice.total = total
|
||||
end
|
||||
end
|
||||
|
@ -19,6 +19,22 @@ class Subscription < ApplicationRecord
|
||||
after_save :notify_admin_subscribed_plan
|
||||
after_save :notify_partner_subscribed_plan, if: :of_partner_plan?
|
||||
|
||||
##
|
||||
# Set the inner properties of the subscription, init the user's credits and save the subscription
|
||||
# into the DB
|
||||
# @return {boolean} true, if the operation succeeded
|
||||
##
|
||||
def init_save
|
||||
return false unless valid?
|
||||
|
||||
set_expiration_date
|
||||
return false unless save
|
||||
|
||||
UsersCredits::Manager.new(user: user).reset_credits
|
||||
true
|
||||
end
|
||||
|
||||
# TODO, remove this method, refactor like services/Reservations::Reserve
|
||||
# @param invoice if true then only the subscription is payed, without reservation
|
||||
# if false then the subscription is payed with reservation
|
||||
# @param payment_method is only used for schedules
|
||||
|
@ -59,4 +59,137 @@ class InvoicesService
|
||||
end
|
||||
{ direction: direction, order_key: order_key }
|
||||
end
|
||||
|
||||
##
|
||||
# Create a Stripe::Invoice with an associated array of Stripe::InvoiceItem matching the given parameters
|
||||
# @param payment_details {Hash} as generated by Price.compute
|
||||
# @param operator_profile_id {Number} ID of the user that operates the invoice generation (may be an admin, a manager or the customer himself)
|
||||
# @param reservation {Reservation} the booking reservation, if any
|
||||
# @param subscription {Subscription} the booking subscription, if any
|
||||
# @param payment_intent_id {String} ID of the Stripe::PaymentIntend, if the current invoice is paid by stripe
|
||||
##
|
||||
def self.create(payment_details, operator_profile_id, reservation: nil, subscription: nil, payment_intent_id: nil)
|
||||
user = reservation&.user || subscription&.user
|
||||
operator = InvoicingProfile.find(operator_profile_id)&.user
|
||||
method = operator&.admin? || (operator&.manager? && operator != user) ? nil : 'stripe'
|
||||
|
||||
invoice = Invoice.new(
|
||||
invoiced: subscription || reservation,
|
||||
invoicing_profile: user.invoicing_profile,
|
||||
statistic_profile: user.statistic_profile,
|
||||
operator_profile_id: operator_profile_id,
|
||||
stp_payment_intent_id: payment_intent_id,
|
||||
payment_method: method
|
||||
)
|
||||
|
||||
InvoicesService.generate_invoice_items(invoice, payment_details, reservation: reservation, subscription: subscription)
|
||||
InvoicesService.set_total_and_coupon(invoice, user, payment_details[:coupon])
|
||||
invoice
|
||||
end
|
||||
|
||||
##
|
||||
# Generate an array of {Stripe::InvoiceItem} with the elements in provided reservation, price included.
|
||||
# @param invoice {Invoice} the parent invoice
|
||||
# @param payment_details {Hash} as generated by Price.compute
|
||||
##
|
||||
def self.generate_invoice_items(invoice, payment_details, reservation: nil, subscription: nil)
|
||||
if reservation
|
||||
case reservation.reservable
|
||||
# === Event reservation ===
|
||||
when Event
|
||||
InvoicesService.generate_event_item(invoice, reservation, payment_details)
|
||||
# === Space|Machine|Training reservation ===
|
||||
else
|
||||
InvoicesService.generate_generic_item(invoice, reservation, payment_details)
|
||||
end
|
||||
end
|
||||
|
||||
return unless subscription || reservation&.plan_id
|
||||
|
||||
subscription = reservation.generate_subscription if !subscription && reservation.plan_id
|
||||
InvoicesService.generate_subscription_item(invoice, subscription, payment_details)
|
||||
end
|
||||
|
||||
##
|
||||
# Generate Stripe::InvoiceItem for each slot in the given reservation and save them in invoice.invoice_items.
|
||||
# This method must be called if reservation.reservable is an Event
|
||||
##
|
||||
def self.generate_event_item(invoice, reservation, payment_details)
|
||||
raise TypeError unless reservation.reservable.class == Event
|
||||
|
||||
reservation.slots.each do |slot|
|
||||
description = "#{reservation.reservable.name}\n"
|
||||
description += if slot.start_at.to_date != slot.end_at.to_date
|
||||
I18n.t('events.from_STARTDATE_to_ENDDATE',
|
||||
STARTDATE: I18n.l(slot.start_at.to_date, format: :long),
|
||||
ENDDATE: I18n.l(slot.end_at.to_date, format: :long)) + ' ' +
|
||||
I18n.t('events.from_STARTTIME_to_ENDTIME',
|
||||
STARTTIME: I18n.l(slot.start_at, format: :hour_minute),
|
||||
ENDTIME: I18n.l(slot.end_at, format: :hour_minute))
|
||||
else
|
||||
"#{I18n.l slot.start_at.to_date, format: :long} #{I18n.l slot.start_at, format: :hour_minute}" \
|
||||
" - #{I18n.l slot.end_at, format: :hour_minute}"
|
||||
end
|
||||
|
||||
price_slot = payment_details[:elements][:slots].detect { |p_slot| p_slot[:start_at].to_time.in_time_zone == slot[:start_at] }
|
||||
invoice.invoice_items.push InvoiceItem.new(
|
||||
amount: price_slot[:price],
|
||||
description: description
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Generate Stripe::InvoiceItem for each slot in the given reservation and save them in invoice.invoice_items.
|
||||
# This method must be called if reservation.reservable is a Space, a Machine or a Training
|
||||
##
|
||||
def self.generate_generic_item(invoice, reservation, payment_details)
|
||||
raise TypeError unless [Space, Machine, Training].include? reservation.reservable.class
|
||||
|
||||
reservation.slots.each do |slot|
|
||||
description = reservation.reservable.name +
|
||||
" #{I18n.l slot.start_at, format: :long} - #{I18n.l slot.end_at, format: :hour_minute}"
|
||||
|
||||
price_slot = payment_details[:elements][:slots].detect { |p_slot| p_slot[:start_at].to_time.in_time_zone == slot[:start_at] }
|
||||
invoice.invoice_items.push InvoiceItem.new(
|
||||
amount: price_slot[:price],
|
||||
description: description
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Generate a Stripe::InvoiceItem for the given subscription and save it in invoice.invoice_items.
|
||||
# This method must be called only with a valid subscription
|
||||
##
|
||||
def self.generate_subscription_item(invoice, subscription, payment_details)
|
||||
raise TypeError unless subscription
|
||||
|
||||
invoice.invoice_items.push InvoiceItem.new(
|
||||
amount: payment_details[:elements][:plan],
|
||||
description: subscription.plan.name,
|
||||
subscription_id: subscription.id
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Set the total price to the reservation's invoice, summing its whole items.
|
||||
# Additionally a coupon may be applied to this invoice to make a discount on the total price
|
||||
# @param invoice {Invoice} the invoice to fill
|
||||
# @param user {User} the customer
|
||||
# @param [coupon] {Coupon} optional coupon to apply to the invoice
|
||||
##
|
||||
def self.set_total_and_coupon(invoice, user, coupon = nil)
|
||||
return unless invoice
|
||||
|
||||
total = invoice.invoice_items.map(&:amount).map(&:to_i).reduce(:+)
|
||||
|
||||
unless coupon.nil?
|
||||
total = CouponService.new.apply(total, coupon, user.id)
|
||||
invoice.coupon_id = coupon.id
|
||||
end
|
||||
|
||||
invoice.total = total
|
||||
end
|
||||
end
|
||||
|
@ -47,11 +47,11 @@ class PaymentScheduleService
|
||||
end
|
||||
|
||||
def create(subscription, total, coupon: nil, operator: nil, payment_method: nil, reservation: nil, user: nil)
|
||||
schedule = compute(subscription.plan, total, coupon)
|
||||
schedule = compute(reservation ? reservation.subscription.plan : subscription.plan, total, coupon)
|
||||
ps = schedule[:payment_schedule]
|
||||
items = schedule[:items]
|
||||
|
||||
ps.scheduled = subscription
|
||||
ps.scheduled = reservation || subscription
|
||||
ps.payment_method = payment_method
|
||||
ps.operator_profile = operator.invoicing_profile
|
||||
ps.invoicing_profile = user.invoicing_profile
|
||||
|
@ -9,8 +9,87 @@ class Reservations::Reserve
|
||||
@operator_profile_id = operator_profile_id
|
||||
end
|
||||
|
||||
def pay_and_save(reservation, payment_details: nil, payment_intent_id: nil, schedule: false)
|
||||
##
|
||||
# Confirm the payment of the given reservation, generate the associated documents and save teh record into
|
||||
# the database.
|
||||
##
|
||||
def pay_and_save(reservation, payment_details: nil, payment_intent_id: nil, schedule: false, payment_method: nil)
|
||||
user = User.find(user_id)
|
||||
reservation.statistic_profile_id = StatisticProfile.find_by(user_id: user_id).id
|
||||
reservation.save_with_payment(operator_profile_id, payment_details, payment_intent_id, schedule: schedule)
|
||||
|
||||
reservation.pre_check
|
||||
payment = if schedule
|
||||
generate_schedule(reservation: reservation,
|
||||
total: payment_details[:before_coupon],
|
||||
operator_profile_id: operator_profile_id,
|
||||
user: user,
|
||||
payment_method: payment_method,
|
||||
coupon_code: payment_details[:coupon])
|
||||
else
|
||||
generate_invoice(reservation, operator_profile_id, payment_details, payment_intent_id)
|
||||
end
|
||||
payment.save
|
||||
debit_user_wallet(payment, user, reservation)
|
||||
reservation.post_save
|
||||
end
|
||||
|
||||
##
|
||||
# Generate the invoice for the given reservation+subscription
|
||||
##
|
||||
def generate_schedule(reservation: nil, total: nil, operator_profile_id: nil, user: nil, payment_method: nil, coupon_code: nil)
|
||||
operator = InvoicingProfile.find(operator_profile_id)&.user
|
||||
coupon = Coupon.find_by(code: coupon_code) unless coupon_code.nil?
|
||||
|
||||
PaymentScheduleService.new.create(
|
||||
nil,
|
||||
total,
|
||||
coupon: coupon,
|
||||
operator: operator,
|
||||
payment_method: payment_method,
|
||||
user: user,
|
||||
reservation: reservation
|
||||
)
|
||||
end
|
||||
|
||||
##
|
||||
# Generate the invoice for the given reservation
|
||||
##
|
||||
def generate_invoice(reservation, operator_profile_id, payment_details, payment_intent_id = nil)
|
||||
InvoicesService.create(
|
||||
payment_details,
|
||||
operator_profile_id,
|
||||
reservation: reservation,
|
||||
payment_intent_id: payment_intent_id
|
||||
)
|
||||
end
|
||||
|
||||
##
|
||||
# Compute the amount decreased from the user's wallet, if applicable
|
||||
# @param payment {Invoice|PaymentSchedule}
|
||||
# @param user {User} the customer
|
||||
# @param coupon {Coupon|String} Coupon object or code
|
||||
##
|
||||
def wallet_amount_debit(payment, user, coupon = nil)
|
||||
total = payment.total
|
||||
total = CouponService.new.apply(total, coupon, user.id) if coupon
|
||||
|
||||
wallet_amount = (user.wallet.amount * 100).to_i
|
||||
|
||||
wallet_amount >= total ? total : wallet_amount
|
||||
end
|
||||
|
||||
##
|
||||
# Subtract the amount of the current reservation from the customer's wallet
|
||||
##
|
||||
def debit_user_wallet(payment, user, reservation)
|
||||
wallet_amount = wallet_amount_debit(payment, user)
|
||||
return unless wallet_amount.present? && wallet_amount != 0
|
||||
|
||||
amount = wallet_amount / 100.0
|
||||
wallet_transaction = WalletService.new(user: user, wallet: user.wallet).debit(amount, reservation)
|
||||
# wallet debit success
|
||||
raise DebitWalletError unless wallet_transaction
|
||||
|
||||
payment.set_wallet_transaction(wallet_amount, wallet_transaction.id)
|
||||
end
|
||||
end
|
||||
|
@ -1,5 +1,7 @@
|
||||
# frozen_string_literal:true
|
||||
|
||||
# From this migration, if the current Invoice is payed with Stripe, it will be stored in database
|
||||
# using stp_payment_intent_id instead of stp_invoice_id
|
||||
class AddStpPaymentIntentIdToInvoices < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
add_column :invoices, :stp_payment_intent_id, :string
|
||||
|
@ -9,6 +9,7 @@ class CreatePaymentScheduleItems < ActiveRecord::Migration[5.2]
|
||||
t.jsonb :details, default: '{}'
|
||||
t.belongs_to :payment_schedule, foreign_key: true
|
||||
t.belongs_to :invoice, foreign_key: true
|
||||
t.string :footprint
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
@ -1473,6 +1473,7 @@ CREATE TABLE public.payment_schedule_items (
|
||||
details jsonb DEFAULT '"{}"'::jsonb,
|
||||
payment_schedule_id bigint,
|
||||
invoice_id bigint,
|
||||
footprint character varying,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL
|
||||
);
|
||||
|
@ -60,6 +60,7 @@ class Subscriptions::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
test 'admin takes a subscription with a payment schedule' do
|
||||
user = User.find_by(username: 'jdupond')
|
||||
plan = Plan.find_by(group_id: user.group.id, type: 'Plan', base_name: 'Abonnement mensualisable')
|
||||
invoice_count = Invoice.count
|
||||
payment_schedule_count = PaymentSchedule.count
|
||||
payment_schedule_items_count = PaymentScheduleItem.count
|
||||
|
||||
@ -106,6 +107,7 @@ class Subscriptions::CreateAsAdminTest < ActionDispatch::IntegrationTest
|
||||
# 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 payment_schedule_count + 1, PaymentSchedule.count, 'missing the payment schedule'
|
||||
assert_equal payment_schedule_items_count + 12, PaymentScheduleItem.count, 'missing some payment schedule items'
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user