1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-29 18:52:22 +01:00

WIP: create subscription on stripe

This commit is contained in:
Sylvain 2020-11-10 17:02:21 +01:00
parent 45800034c0
commit 78847bdb4b
9 changed files with 85 additions and 22 deletions

View File

@ -20,7 +20,9 @@ class API::SubscriptionsController < API::ApiController
@subscription = Subscription.new(subscription_params)
is_subscribe = Subscriptions::Subscribe.new(current_user.invoicing_profile.id, user_id)
.pay_and_save(@subscription, coupon: coupon_params[:coupon_code], invoice: true)
.pay_and_save(@subscription, coupon: coupon_params[:coupon_code],
invoice: true,
schedule: params[:subcription][:payment_schedule])
if is_subscribe
render :show, status: :created, location: @subscription

View File

@ -8,4 +8,10 @@ class PaymentSchedule < ApplicationRecord
belongs_to :coupon
belongs_to :invoicing_profile
belongs_to :operator_profile, foreign_key: :operator_profile_id, class_name: 'InvoicingProfile'
after_create :create_stripe_subscription
def create_stripe_subscription
StripeWorker.perform_async(:create_stripe_subscription, id)
end
end

View File

@ -20,7 +20,7 @@ class Subscription < ApplicationRecord
# @param invoice if true then only the subscription is payed, without reservation
# if false then the subscription is payed with reservation
def save_with_payment(operator_profile_id, invoice = true, coupon_code = nil, payment_intent_id = nil)
def save_with_payment(operator_profile_id, invoice = true, coupon_code = nil, payment_intent_id = nil, schedule = nil)
return false unless valid?
set_expiration_date
@ -33,16 +33,30 @@ class Subscription < ApplicationRecord
# debit wallet
wallet_transaction = debit_user_wallet
invoc = generate_invoice(operator_profile_id, coupon_code, payment_intent_id)
payment = if schedule
generate_schedule(operator_profile_id, coupon_code, payment_intent_id)
else
generate_invoice(operator_profile_id, coupon_code, payment_intent_id)
end
if wallet_transaction
invoc.wallet_amount = @wallet_amount_debit
invoc.wallet_transaction_id = wallet_transaction.id
payment.wallet_amount = @wallet_amount_debit
payment.wallet_transaction_id = wallet_transaction.id
end
invoc.save
payment.save
end
true
end
def generate_schedule(operator_profile_id, coupon_code = nil, payment_intent_id = nil)
operator = InvoicingProfile.find(operator_profile_id)&.user
method = operator&.admin? || (operator&.manager? && operator != user) ? nil : 'stripe'
coupon = Coupon.find_by(code: coupon_code) unless coupon_code.nil?
schedule = PaymentScheduleService.new.create(self, plan.amount, coupon, operator, method)
end
def generate_invoice(operator_profile_id, coupon_code = nil, payment_intent_id = nil)
coupon_id = nil
total = plan.amount

View File

@ -199,8 +199,8 @@ class PDF::Invoice < Prawn::Document
elsif cp.type == 'amount_off'
# refunds of invoices with cash coupons: we need to ventilate coupons on paid items
if invoice.is_a?(Avoir)
paid_items = invoice.invoice.invoice_items.select{ |ii| ii.amount.positive? }.length
refund_items = invoice.invoice_items.select{ |ii| ii.amount.positive? }.length
paid_items = invoice.invoice.invoice_items.select { |ii| ii.amount.positive? }.length
refund_items = invoice.invoice_items.select { |ii| ii.amount.positive? }.length
discount = ((invoice.coupon.amount_off / paid_items) * refund_items) / 100.00
else

View File

@ -41,4 +41,17 @@ class PaymentScheduleService
end
{ payment_schedule: ps, items: items }
end
def create(subscription, total, coupon, operator, payment_method)
schedule = compute(subscription.plan, total, coupon)
ps = schedule[:payment_schedule]
items = schedule[:items]
ps.scheduled = subscription
ps.payment_method = payment_method
ps.operator_profile_id = operator
items.each do |item|
item.payment_schedule = ps
end
end
end

View File

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

View File

@ -73,4 +73,32 @@ class StripeWorker
)
plan.update_columns(stp_price_id: price.id)
end
def create_stripe_subscription(payment_schedule_id, first_invoice_items)
payment_schedule = PaymentSchedule.find(payment_schedule_id)
items = []
first_invoice_items.each do |fii|
# TODO, fill this prices with real data
price = Stripe::Price.create({
unit_amount: 2000,
currency: 'eur',
recurring: { interval: 'month' },
product_data: {
name: 'lorem ipsum'
}
},
{ api_key: Setting.get('stripe_secret_key') })
items.push(price: price[:id])
end
Stripe::Subscription.create({
customer: payment_schedule.invoicing_profile.user.stp_customer_id,
cancel_at: payment_schedule.scheduled.expiration_date,
promotion_code: payment_schedule.coupon&.code,
add_invoice_items: items,
items: [
{ price: payment_schedule.scheduled.plan.stp_price_id }
]
}, { api_key: Setting.get('stripe_secret_key') })
end
end

View File

@ -16,7 +16,7 @@ class CreatePaymentSchedules < ActiveRecord::Migration[5.2]
t.string :footprint
t.string :environment
t.belongs_to :invoicing_profile, foreign_key: true
t.references :operator_profile_id, foreign_key: { to_table: 'invoicing_profiles' }
t.references :operator_profile, foreign_key: { to_table: 'invoicing_profiles' }
t.timestamps
end

View File

@ -1513,7 +1513,7 @@ CREATE TABLE public.payment_schedules (
footprint character varying,
environment character varying,
invoicing_profile_id bigint,
operator_profile_id_id bigint,
operator_profile_id bigint,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL
);
@ -4554,10 +4554,10 @@ CREATE INDEX index_payment_schedules_on_invoicing_profile_id ON public.payment_s
--
-- Name: index_payment_schedules_on_operator_profile_id_id; Type: INDEX; Schema: public; Owner: -
-- Name: index_payment_schedules_on_operator_profile_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_payment_schedules_on_operator_profile_id_id ON public.payment_schedules USING btree (operator_profile_id_id);
CREATE INDEX index_payment_schedules_on_operator_profile_id ON public.payment_schedules USING btree (operator_profile_id);
--
@ -5378,6 +5378,14 @@ ALTER TABLE ONLY public.projects_machines
ADD CONSTRAINT fk_rails_88b280c24c FOREIGN KEY (machine_id) REFERENCES public.machines(id);
--
-- Name: payment_schedules fk_rails_8b73dd8d7d; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.payment_schedules
ADD CONSTRAINT fk_rails_8b73dd8d7d FOREIGN KEY (operator_profile_id) REFERENCES public.invoicing_profiles(id);
--
-- Name: availability_tags fk_rails_8cb4e921f7; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@ -5442,14 +5450,6 @@ ALTER TABLE ONLY public.projects_themes
ADD CONSTRAINT fk_rails_b021a22658 FOREIGN KEY (theme_id) REFERENCES public.themes(id);
--
-- Name: payment_schedules fk_rails_b38f5b39f6; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.payment_schedules
ADD CONSTRAINT fk_rails_b38f5b39f6 FOREIGN KEY (operator_profile_id_id) REFERENCES public.invoicing_profiles(id);
--
-- Name: statistic_profiles fk_rails_bba64e5eb9; Type: FK CONSTRAINT; Schema: public; Owner: -
--