mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-19 13:54:25 +01:00
handle reservations+subscription w/ schedule
integration testing for payment schedule debug reservation process
This commit is contained in:
parent
c3c881d2a8
commit
908ccf5bab
@ -103,7 +103,10 @@ class API::PaymentsController < API::ApiController
|
||||
current_user.id
|
||||
end
|
||||
is_reserve = Reservations::Reserve.new(user_id, current_user.invoicing_profile.id)
|
||||
.pay_and_save(@reservation, payment_details: details, payment_intent_id: intent.id)
|
||||
.pay_and_save(@reservation,
|
||||
payment_details: details,
|
||||
payment_intent_id: intent.id,
|
||||
schedule: params[:cart_items][:reservation][:payment_schedule])
|
||||
if intent.class == Stripe::PaymentIntent
|
||||
Stripe::PaymentIntent.update(
|
||||
intent.id,
|
||||
|
@ -35,7 +35,9 @@ class API::ReservationsController < API::ApiController
|
||||
|
||||
@reservation = Reservation.new(reservation_params)
|
||||
is_reserve = Reservations::Reserve.new(user_id, current_user.invoicing_profile.id)
|
||||
.pay_and_save(@reservation, payment_details: price[:price_details])
|
||||
.pay_and_save(@reservation,
|
||||
payment_details: price[:price_details],
|
||||
schedule: params[:reservation][:payment_schedule])
|
||||
|
||||
if is_reserve
|
||||
SubscriptionExtensionAfterReservation.new(@reservation).extend_subscription_if_eligible
|
||||
|
@ -120,7 +120,7 @@ class Reservation < ApplicationRecord
|
||||
pending_invoice_items.each(&:delete)
|
||||
end
|
||||
|
||||
def save_with_payment(operator_profile_id, payment_details, payment_intent_id = nil)
|
||||
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'
|
||||
|
||||
@ -138,7 +138,7 @@ class Reservation < ApplicationRecord
|
||||
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)
|
||||
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,
|
||||
|
@ -10,8 +10,7 @@ class Reservations::Reserve
|
||||
end
|
||||
|
||||
def pay_and_save(reservation, payment_details: nil, payment_intent_id: nil, schedule: false)
|
||||
# TODO, pass the schedule payment up to subscription.save_with_payment(... schedule: schedule)
|
||||
reservation.statistic_profile_id = StatisticProfile.find_by(user_id: user_id).id
|
||||
reservation.save_with_payment(operator_profile_id, payment_details, payment_intent_id)
|
||||
reservation.save_with_payment(operator_profile_id, payment_details, payment_intent_id, schedule: schedule)
|
||||
end
|
||||
end
|
||||
|
@ -53,7 +53,6 @@ class StripeWorker
|
||||
{ name: object.name },
|
||||
{ api_key: Setting.get('stripe_secret_key') }
|
||||
)
|
||||
p.product
|
||||
else
|
||||
product = Stripe::Product.create(
|
||||
{
|
||||
|
@ -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,
|
||||
@ -1046,8 +1046,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,
|
||||
stp_invoice_id character varying,
|
||||
total integer,
|
||||
created_at timestamp without time zone,
|
||||
@ -1227,15 +1227,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
|
||||
);
|
||||
|
||||
|
||||
@ -1656,8 +1656,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
|
||||
@ -1972,8 +1972,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
|
||||
);
|
||||
@ -2005,8 +2005,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
|
||||
);
|
||||
@ -2942,8 +2942,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,
|
||||
@ -4032,6 +4032,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: -
|
||||
--
|
||||
@ -5096,29 +5104,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: -
|
||||
--
|
||||
@ -5653,7 +5638,6 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20140605125131'),
|
||||
('20140605142133'),
|
||||
('20140605151442'),
|
||||
('20140606133116'),
|
||||
('20140609092700'),
|
||||
('20140609092827'),
|
||||
('20140610153123'),
|
||||
@ -5722,14 +5706,12 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20150507075620'),
|
||||
('20150512123546'),
|
||||
('20150520132030'),
|
||||
('20150520133409'),
|
||||
('20150526130729'),
|
||||
('20150527153312'),
|
||||
('20150529113555'),
|
||||
('20150601125944'),
|
||||
('20150603104502'),
|
||||
('20150603104658'),
|
||||
('20150603133050'),
|
||||
('20150604081757'),
|
||||
('20150604131525'),
|
||||
('20150608142234'),
|
||||
@ -5811,7 +5793,6 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20160905142700'),
|
||||
('20160906094739'),
|
||||
('20160906094847'),
|
||||
('20160906145713'),
|
||||
('20160915105234'),
|
||||
('20161123104604'),
|
||||
('20170109085345'),
|
||||
|
10
test/fixtures/history_values.yml
vendored
10
test/fixtures/history_values.yml
vendored
@ -100,7 +100,7 @@ value_history_10:
|
||||
id: 10
|
||||
setting_id: 10
|
||||
invoicing_profile_id: 1
|
||||
value: YYMMmmmX[/VL]R[/A]S[/E]
|
||||
value: YYMMmmmX[/VL]R[/A]
|
||||
created_at: 2018-12-17 11:23:01.603733000 Z
|
||||
updated_at: 2018-12-17 11:23:01.603733000 Z
|
||||
footprint: ed23a2eb1903befc977621bc3c3b19aad831fe550ebaa99e9299238b3d93c275
|
||||
@ -693,3 +693,11 @@ history_value_73:
|
||||
value: true
|
||||
created_at: 2020-06-17 10:48:19.002417000 Z
|
||||
updated_at: 2020-06-17 10:48:19.002417000 Z
|
||||
|
||||
value_history_74:
|
||||
id: 74
|
||||
setting_id: 10
|
||||
invoicing_profile_id: 1
|
||||
value: YYMMmmmX[/VL]R[/A]S[/E]
|
||||
created_at: 2020-12-14 14:37:35.615124000 Z
|
||||
updated_at: 2020-12-14 14:37:35.615124000 Z
|
||||
|
6
test/fixtures/machines.yml
vendored
6
test/fixtures/machines.yml
vendored
@ -22,6 +22,7 @@ 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
|
||||
@ -38,6 +39,7 @@ 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
|
||||
@ -54,6 +56,7 @@ 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
|
||||
@ -67,6 +70,7 @@ 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
|
||||
@ -89,6 +93,7 @@ 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
|
||||
@ -123,3 +128,4 @@ 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
|
||||
|
26
test/fixtures/plans.yml
vendored
26
test/fixtures/plans.yml
vendored
@ -15,6 +15,8 @@ plan_1:
|
||||
base_name: Mensuel
|
||||
ui_weight: 1
|
||||
interval_count: 1
|
||||
slug: mensuel
|
||||
stp_product_id: prod_IZPyXhfyNiGkWR
|
||||
|
||||
plan_2:
|
||||
id: 2
|
||||
@ -32,6 +34,8 @@ plan_2:
|
||||
base_name: Sleede
|
||||
ui_weight: 5
|
||||
interval_count: 2
|
||||
slug: sleede
|
||||
stp_product_id: prod_IZPykam7a4satn
|
||||
|
||||
plan_3:
|
||||
id: 3
|
||||
@ -49,4 +53,26 @@ plan_3:
|
||||
type: Plan
|
||||
base_name: Mensuel tarif réduit
|
||||
ui_weight: 0
|
||||
interval_count: 1*
|
||||
slug: mensuel-tarif-reduit
|
||||
stp_product_id: prod_IZPyM4N36h86G0
|
||||
|
||||
plan_schedulable:
|
||||
id: 4
|
||||
name: Abonnement mensualisable - standard, association, year
|
||||
amount: 113600
|
||||
interval: year
|
||||
group_id: 1
|
||||
stp_plan_id:
|
||||
created_at: 2020-12-14 14:10:11.056241000 Z
|
||||
updated_at: 2020-12-14 14:10:11.137421000 Z
|
||||
training_credit_nb: 1
|
||||
is_rolling: true
|
||||
description:
|
||||
type: Plan
|
||||
base_name: Abonnement mensualisable
|
||||
ui_weight: 10
|
||||
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,3 +7,4 @@ 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,6 +7,7 @@ training_1:
|
||||
nb_total_places:
|
||||
slug: formation-imprimante-3d
|
||||
description:
|
||||
stp_product_id: prod_IZPyXw6BDBBFOg
|
||||
|
||||
training_2:
|
||||
id: 2
|
||||
@ -16,6 +17,7 @@ training_2:
|
||||
nb_total_places:
|
||||
slug: formation-laser-vinyle
|
||||
description:
|
||||
stp_product_id: prod_IZPytTl1wSB5jH
|
||||
|
||||
training_3:
|
||||
id: 3
|
||||
@ -25,6 +27,7 @@ training_3:
|
||||
nb_total_places:
|
||||
slug: formation-petite-fraiseuse-numerique
|
||||
description:
|
||||
stp_product_id: prod_IZPyAA1A4QfEyL
|
||||
|
||||
training_4:
|
||||
id: 4
|
||||
@ -34,6 +37,7 @@ training_4:
|
||||
nb_total_places:
|
||||
slug: formation-shopbot-grande-fraiseuse
|
||||
description:
|
||||
stp_product_id: prod_IZPyU27NjDSmqB
|
||||
|
||||
training_5:
|
||||
id: 5
|
||||
@ -43,3 +47,4 @@ training_5:
|
||||
nb_total_places:
|
||||
slug: formation-logiciel-2d
|
||||
description:
|
||||
stp_product_id: prod_IZPyvdgQHMByB3
|
||||
|
@ -1,5 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
@user = User.find_by(username: 'jdupond')
|
||||
@ -166,4 +168,48 @@ class Subscriptions::CreateAsUserTest < ActionDispatch::IntegrationTest
|
||||
assert_equal invoice.wallet_amount / 100.0, transaction.amount
|
||||
assert_equal invoice.wallet_transaction_id, transaction.id
|
||||
end
|
||||
|
||||
test 'user takes a subscription with payment schedule' do
|
||||
plan = Plan.find_by(group_id: @user.group.id, type: 'Plan', base_name: 'Abonnement mensualisable')
|
||||
|
||||
VCR.use_cassette('subscriptions_user_setup_intent') do
|
||||
get "/api/payments/setup_intent/#{@user.id}"
|
||||
end
|
||||
|
||||
# Check response format & status
|
||||
assert_equal 200, response.status, response.body
|
||||
assert_equal Mime[:json], response.content_type
|
||||
|
||||
# Check the correct object was signaled
|
||||
setup_intent = json_response(response.body)
|
||||
|
||||
VCR.use_cassette('subscriptions_user_create_with_payment_schedule') do
|
||||
post '/api/payments/confirm_payment',
|
||||
params: {
|
||||
payment_method_id: stripe_payment_method,
|
||||
cart_items: {
|
||||
subscription: {
|
||||
plan_id: plan.id,
|
||||
payment_schedule: true,
|
||||
payment_method: 'stripe'
|
||||
}
|
||||
},
|
||||
setup_intent_id: setup_intent[:client_secret]
|
||||
}.to_json, headers: default_headers
|
||||
end
|
||||
|
||||
# Check response format & status
|
||||
assert_equal 201, response.status, response.body
|
||||
assert_equal Mime[:json], response.content_type
|
||||
|
||||
# Check the correct plan was subscribed
|
||||
subscription = json_response(response.body)
|
||||
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
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user