spree_stripe_subscriptions 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +91 -0
- data/.rubocop.yml +26 -0
- data/.travis.yml +37 -0
- data/Gemfile +12 -0
- data/LICENSE +26 -0
- data/README.md +72 -0
- data/Rakefile +21 -0
- data/app/controllers/spree/admin/stripe_configurations_controller.rb +6 -0
- data/app/controllers/spree/admin/stripe_customers_controller.rb +6 -0
- data/app/controllers/spree/admin/stripe_plans_controller.rb +36 -0
- data/app/controllers/spree/admin/stripe_subscription_events_controller.rb +6 -0
- data/app/controllers/spree/admin/stripe_subscriptions_controller.rb +6 -0
- data/app/controllers/spree/stripe_plans_controller.rb +20 -0
- data/app/controllers/spree/stripe_subscriptions_controller.rb +166 -0
- data/app/controllers/spree/stripe_webhooks_controller.rb +56 -0
- data/app/models/spree/stripe_configuration.rb +28 -0
- data/app/models/spree/stripe_customer.rb +30 -0
- data/app/models/spree/stripe_invoice.rb +21 -0
- data/app/models/spree/stripe_plan.rb +104 -0
- data/app/models/spree/stripe_subscription.rb +167 -0
- data/app/models/spree/stripe_subscription_event.rb +10 -0
- data/app/models/spree_stripe_subscriptions/configuration.rb +15 -0
- data/app/models/spree_stripe_subscriptions/user_decorator.rb +50 -0
- data/app/overrides/spree/admin/shared/_main_menu.rb +13 -0
- data/app/serializers/.gitkeep +0 -0
- data/app/services/.gitkeep +0 -0
- data/app/views/spree/admin/shared/sub_menu/_stripe_subscriptions.html.erb +8 -0
- data/app/views/spree/admin/stripe_configurations/_form.html.erb +42 -0
- data/app/views/spree/admin/stripe_configurations/edit.html.erb +17 -0
- data/app/views/spree/admin/stripe_configurations/index.html.erb +44 -0
- data/app/views/spree/admin/stripe_configurations/new.html.erb +13 -0
- data/app/views/spree/admin/stripe_customers/index.html.erb +36 -0
- data/app/views/spree/admin/stripe_plans/_form.html.erb +50 -0
- data/app/views/spree/admin/stripe_plans/edit.html.erb +15 -0
- data/app/views/spree/admin/stripe_plans/index.html.erb +59 -0
- data/app/views/spree/admin/stripe_plans/new.html.erb +15 -0
- data/app/views/spree/admin/stripe_subscription_events/index.html.erb +36 -0
- data/app/views/spree/admin/stripe_subscriptions/index.html.erb +40 -0
- data/app/views/spree/stripe_plans/index.html.erb +77 -0
- data/bin/rails +8 -0
- data/config/initializers/stripe.rb +11 -0
- data/config/locales/en.yml +80 -0
- data/config/routes.rb +27 -0
- data/db/migrate/20221130094411_add_spree_stripe_configuration_model.rb +14 -0
- data/db/migrate/20221130095015_add_spree_stripe_plan_model.rb +23 -0
- data/db/migrate/20221130100526_add_spree_stripe_customer.rb +11 -0
- data/db/migrate/20221130100903_add_spree_stripe_subscription_model.rb +23 -0
- data/db/migrate/20221130102650_add_spree_stripe_subscription_events_model.rb +16 -0
- data/db/migrate/20221202111450_add_weightage_to_stripe_plan.rb +10 -0
- data/db/migrate/20221209065244_add_schedules_to_subscription.rb +6 -0
- data/db/migrate/20221209094013_add_stripe_invoices.rb +33 -0
- data/db/migrate/20221209131817_add_user_to_invoice.rb +5 -0
- data/db/migrate/20221221080141_add_extra_plan_fields.rb +8 -0
- data/lib/generators/spree_stripe_subscriptions/install/install_generator.rb +20 -0
- data/lib/spree_stripe_subscriptions/engine.rb +24 -0
- data/lib/spree_stripe_subscriptions/factories.rb +6 -0
- data/lib/spree_stripe_subscriptions/version.rb +11 -0
- data/lib/spree_stripe_subscriptions.rb +4 -0
- data/spree_stripe_subscriptions.gemspec +34 -0
- metadata +207 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= link_to I18n.t('spree_stripe_subscriptions.admin.stripe_configurations'), spree.admin_stripe_configurations_url %> /
|
3
|
+
<%= link_to @stripe_configuration.name, spree.edit_admin_stripe_configuration_url(@stripe_configuration) %> /
|
4
|
+
<%= I18n.t('spree_stripe_subscriptions.admin.stripe_plans') %>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<% content_for :page_actions do %>
|
8
|
+
<%= button_link_to I18n.t('spree_stripe_subscriptions.admin.new_stripe_plan'), new_object_url, class: "btn-success", icon: 'add.svg' %>
|
9
|
+
<% end if can? :create, Spree::StripePlan %>
|
10
|
+
|
11
|
+
<% if @stripe_plans.any? %>
|
12
|
+
<div class="table-responsive">
|
13
|
+
<table class="table sortable" data-hook
|
14
|
+
data-sortable-link="<%= update_positions_admin_stripe_configuration_stripe_plans_url(@stripe_configuration) %>">
|
15
|
+
<thead>
|
16
|
+
<tr>
|
17
|
+
<th title="<%= I18n.t('spree_stripe_subscriptions.models.stripe_plans.weightage_title') %>"><%= I18n.t('spree_stripe_subscriptions.models.stripe_plans.weightage') %></th>
|
18
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_plans.stripe_plan_id') %></th>
|
19
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_plans.name') %></th>
|
20
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_plans.currency') %></th>
|
21
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_plans.amount') %></th>
|
22
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_plans.interval') %></th>
|
23
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_plans.interval_count') %></th>
|
24
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_plans.trial_period_days') %></th>
|
25
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_plans.active') %></th>
|
26
|
+
<th></th>
|
27
|
+
</tr>
|
28
|
+
</thead>
|
29
|
+
<tbody>
|
30
|
+
<% @stripe_plans.each do |stripe_plan| %>
|
31
|
+
<tr id="<%= spree_dom_id stripe_plan %>">
|
32
|
+
<td class="move-handle text-center">
|
33
|
+
<%= svg_icon name: "sort.svg", width: '18', height: '18' %>
|
34
|
+
</td>
|
35
|
+
<td><%= stripe_plan.stripe_plan_id %></td>
|
36
|
+
<td><%= stripe_plan.name %></td>
|
37
|
+
<td><%= stripe_plan.currency.upcase %></td>
|
38
|
+
<td><%= stripe_plan.amount %></td>
|
39
|
+
<td><%= stripe_plan.interval.capitalize %></td>
|
40
|
+
<td><%= stripe_plan.interval_count %></td>
|
41
|
+
<td><%= stripe_plan.trial_period_days %></td>
|
42
|
+
<td><%= active_badge(stripe_plan.active) %></td>
|
43
|
+
<td class="actions">
|
44
|
+
<span class="d-flex justify-content-end">
|
45
|
+
<%= link_to_with_icon('edit.svg', I18n.t('spree_stripe_subscriptions.admin.edit'), spree.edit_admin_stripe_configuration_stripe_plan_url(@stripe_configuration, stripe_plan), class: 'btn btn-primary btn-sm', no_text: true, data: { action: 'edit' }) if can? :edit, stripe_plan %>
|
46
|
+
<%= link_to_delete(stripe_plan, { url: spree.admin_stripe_configuration_stripe_plan_url(@stripe_configuration, stripe_plan), no_text: true }) if can? :delete, stripe_plan %>
|
47
|
+
</span>
|
48
|
+
</tr>
|
49
|
+
<% end %>
|
50
|
+
</tbody>
|
51
|
+
</table>
|
52
|
+
</div>
|
53
|
+
<% else %>
|
54
|
+
<div class="alert alert-info no-objects-found">
|
55
|
+
<%= I18n.t('spree_stripe_subscriptions.admin.no_resource_found',
|
56
|
+
resource: I18n.t('spree_stripe_subscriptions.admin.stripe_plans')) %>,
|
57
|
+
<%= link_to(I18n.t('spree_stripe_subscriptions.admin.add_one'), new_object_url) if can? :create, Spree::StripePlan %>
|
58
|
+
</div>
|
59
|
+
<% end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= link_to I18n.t('spree_stripe_subscriptions.admin.stripe_configurations'), spree.admin_stripe_configurations_url %> /
|
3
|
+
<%= link_to @stripe_configuration.name, spree.edit_admin_stripe_configuration_url(@stripe_configuration) %> /
|
4
|
+
<%= link_to I18n.t('spree_stripe_subscriptions.admin.stripe_plans'), spree.admin_stripe_configuration_stripe_plans_url(@stripe_configuration) %> /
|
5
|
+
<%= I18n.t('spree_stripe_subscriptions.admin.new_stripe_plan') %>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<%= render partial: 'spree/admin/shared/error_messages', locals: { target: @stripe_plan } %>
|
9
|
+
|
10
|
+
<%= form_for [:admin, @stripe_configuration, @stripe_plan] do |f| %>
|
11
|
+
<fieldset>
|
12
|
+
<%= render partial: 'form', locals: { f: f } %>
|
13
|
+
<%= render partial: 'spree/admin/shared/new_resource_links' %>
|
14
|
+
</fieldset>
|
15
|
+
<% end %>
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= I18n.t('spree_stripe_subscriptions.admin.stripe_subscription_events') %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% if @stripe_subscription_events.any? %>
|
6
|
+
<div class="table-responsive">
|
7
|
+
<table class="table">
|
8
|
+
<thead>
|
9
|
+
<tr>
|
10
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_subscription_events.event_id') %></th>
|
11
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_subscription_events.event_type') %></th>
|
12
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_subscription_events.stripe_subscription_id') %></th>
|
13
|
+
<th></th>
|
14
|
+
</tr>
|
15
|
+
</thead>
|
16
|
+
<tbody>
|
17
|
+
<% @stripe_subscription_events.each do |stripe_subscription_event| %>
|
18
|
+
<tr id="<%= spree_dom_id stripe_subscription_event %>">
|
19
|
+
<td><%= stripe_subscription_event.event_id %></td>
|
20
|
+
<td><%= stripe_subscription_event.event_type %></td>
|
21
|
+
<td><%= stripe_subscription_event.subscription.stripe_subscription_id %></td>
|
22
|
+
<td class="actions">
|
23
|
+
<span class="d-flex justify-content-end">
|
24
|
+
<%#= link_to_edit(stripe_subscription_event, no_text: true) if can? :edit, stripe_subscription_event %>
|
25
|
+
<%#= link_to_delete(stripe_subscription_event, no_text: true) if can? :delete, stripe_subscription_event %>
|
26
|
+
</span>
|
27
|
+
</tr>
|
28
|
+
<% end %>
|
29
|
+
</tbody>
|
30
|
+
</table>
|
31
|
+
</div>
|
32
|
+
<% else %>
|
33
|
+
<div class="alert alert-info no-objects-found">
|
34
|
+
<%= I18n.t('spree_stripe_subscriptions.admin.no_resource_found', resource: I18n.t('spree_stripe_subscriptions.admin.stripe_subscription_events')) %>
|
35
|
+
</div>
|
36
|
+
<% end %>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= I18n.t('spree_stripe_subscriptions.admin.stripe_subscriptions') %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% if @stripe_subscriptions.any? %>
|
6
|
+
<div class="table-responsive">
|
7
|
+
<table class="table">
|
8
|
+
<thead>
|
9
|
+
<tr>
|
10
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_subscriptions.stripe_subscription_id') %></th>
|
11
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_subscriptions.plan') %></th>
|
12
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_subscriptions.user') %></th>
|
13
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_subscriptions.customer') %></th>
|
14
|
+
<th><%= I18n.t('spree_stripe_subscriptions.models.stripe_subscriptions.status') %></th>
|
15
|
+
<th></th>
|
16
|
+
</tr>
|
17
|
+
</thead>
|
18
|
+
<tbody>
|
19
|
+
<% @stripe_subscriptions.each do |stripe_subscription| %>
|
20
|
+
<tr id="<%= spree_dom_id stripe_subscription %>">
|
21
|
+
<td><%= stripe_subscription.stripe_subscription_id %></td>
|
22
|
+
<td><%= stripe_subscription.plan.name %></td>
|
23
|
+
<td><%= stripe_subscription.user.email %></td>
|
24
|
+
<td><%= stripe_subscription.customer.stripe_customer_id %></td>
|
25
|
+
<td><%= stripe_subscription.status.capitalize %></td>
|
26
|
+
<td class="actions">
|
27
|
+
<span class="d-flex justify-content-end">
|
28
|
+
<%#= link_to_edit(stripe_subscription, no_text: true) if can? :edit, stripe_subscription %>
|
29
|
+
<%#= link_to_delete(stripe_subscription, no_text: true) if can? :delete, stripe_subscription %>
|
30
|
+
</span>
|
31
|
+
</tr>
|
32
|
+
<% end %>
|
33
|
+
</tbody>
|
34
|
+
</table>
|
35
|
+
</div>
|
36
|
+
<% else %>
|
37
|
+
<div class="alert alert-info no-objects-found">
|
38
|
+
<%= I18n.t('spree_stripe_subscriptions.admin.no_resource_found', resource: I18n.t('spree_stripe_subscriptions.admin.stripe_subscriptions')) %>
|
39
|
+
</div>
|
40
|
+
<% end %>
|
@@ -0,0 +1,77 @@
|
|
1
|
+
<div class="container">
|
2
|
+
<div class="row my-5">
|
3
|
+
<div class="col-12 text-center">
|
4
|
+
<h2><%= I18n.t('spree_stripe_subscriptions.plans') %></h2>
|
5
|
+
</div>
|
6
|
+
</div>
|
7
|
+
<hr/>
|
8
|
+
<div class="row my-5">
|
9
|
+
<% @stripe_plans.each do |plan| %>
|
10
|
+
<div class="col-sm-12 py-4">
|
11
|
+
<div class="card text-center">
|
12
|
+
<div class="card-body">
|
13
|
+
<h5 class="card-title"><%= plan.name %></h5>
|
14
|
+
<p class="card-text">
|
15
|
+
<%= number_to_currency(plan.amount, precision: 2) %> /
|
16
|
+
<%= plan.interval_count %> <%= plan.interval.pluralize(plan.interval_count) %> <br/>
|
17
|
+
<%= plan.trial_period_days %> <%= 'day'.pluralize(plan.trial_period_days) %> trial
|
18
|
+
</p>
|
19
|
+
<% if spree_current_user %>
|
20
|
+
<% if @active_subscription.present? && @active_subscription.plan_id == plan.id %>
|
21
|
+
<% if @active_subscription.cancel_at_period_end %>
|
22
|
+
<p class="card-text">
|
23
|
+
Your subscription ends on <%= @active_subscription.cancel_at %>
|
24
|
+
</p>
|
25
|
+
<% else %>
|
26
|
+
<%= button_link_to I18n.t('spree_stripe_subscriptions.cancel_renewal'),
|
27
|
+
stripe_plan_stripe_subscription_url(plan, @active_subscription),
|
28
|
+
method: :patch, class: 'btn btn-primary btn-danger',
|
29
|
+
confirm: "Do you want to cancel renewal?" %>
|
30
|
+
<br/>
|
31
|
+
<% end %>
|
32
|
+
<%= button_link_to I18n.t('spree_stripe_subscriptions.unsubscribe'),
|
33
|
+
stripe_plan_stripe_subscription_url(plan, @active_subscription),
|
34
|
+
method: :delete, class: 'btn btn-primary btn-danger',
|
35
|
+
confirm: "Do you want to unsubscribe?" %>
|
36
|
+
<br/>
|
37
|
+
<%= button_link_to I18n.t('spree_stripe_subscriptions.update_payment_method'),
|
38
|
+
change_payment_details_stripe_plan_stripe_subscription_url(plan, @active_subscription),
|
39
|
+
method: :post, class: 'btn btn-primary btn-danger' %>
|
40
|
+
<% elsif @active_subscription.present? && @active_subscription.next_plan_id == plan.id %>
|
41
|
+
<p class="card-text">
|
42
|
+
Your next subscription starts on <%= @active_subscription.current_period_end %>
|
43
|
+
</p>
|
44
|
+
<% else %>
|
45
|
+
<% if @active_subscription.present? %>
|
46
|
+
<%
|
47
|
+
action_type = if @active_subscription.plan.weightage < plan.weightage
|
48
|
+
:upgrade
|
49
|
+
else
|
50
|
+
:downgrade
|
51
|
+
end
|
52
|
+
action_url = if action_type == :upgrade
|
53
|
+
stripe_plan_stripe_subscriptions_url(plan)
|
54
|
+
else
|
55
|
+
downgrade_stripe_plan_stripe_subscription_url(plan, @active_subscription)
|
56
|
+
end
|
57
|
+
%>
|
58
|
+
<%= button_link_to I18n.t("spree_stripe_subscriptions.#{action_type}"),
|
59
|
+
action_url,
|
60
|
+
method: :post,
|
61
|
+
class: 'btn btn-primary btn-default' %>
|
62
|
+
<% else %>
|
63
|
+
<%= button_link_to I18n.t('spree_stripe_subscriptions.subscribe'),
|
64
|
+
stripe_plan_stripe_subscriptions_url(plan),
|
65
|
+
method: :post,
|
66
|
+
class: 'btn btn-primary btn-default' %>
|
67
|
+
<% end %>
|
68
|
+
<% end %>
|
69
|
+
<% end %>
|
70
|
+
</div>
|
71
|
+
</div>
|
72
|
+
</div>
|
73
|
+
<% end %>
|
74
|
+
</div>
|
75
|
+
</div>
|
76
|
+
|
77
|
+
|
data/bin/rails
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" from the root of your extension
|
3
|
+
|
4
|
+
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
5
|
+
ENGINE_PATH = File.expand_path('../../lib/spree_stripe_subscriptions/engine', __FILE__)
|
6
|
+
|
7
|
+
require 'rails/all'
|
8
|
+
require 'rails/engine/commands'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'stripe'
|
2
|
+
require 'stripe_tester' if Rails.env.development? || Rails.env.test?
|
3
|
+
|
4
|
+
Stripe.api_version = '2020-03-02'
|
5
|
+
|
6
|
+
begin
|
7
|
+
Stripe.api_key = Spree::StripeConfiguration.active.last&.preferred_secret_key
|
8
|
+
rescue ActiveRecord::StatementInvalid => e
|
9
|
+
Rails.logger.error e
|
10
|
+
# Ignored
|
11
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# Sample localization file for English. Add more files in this directory for other locales.
|
2
|
+
# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
|
3
|
+
|
4
|
+
en:
|
5
|
+
spree_stripe_subscriptions:
|
6
|
+
admin:
|
7
|
+
stripe_configurations: Stripe Configurations
|
8
|
+
new_stripe_configuration: New Stripe Configuration
|
9
|
+
stripe_plans: Stripe Plans
|
10
|
+
new_stripe_plan: Stripe Plan
|
11
|
+
stripe_customers: Stripe Customers
|
12
|
+
stripe_subscriptions: Stripe Subscriptions
|
13
|
+
stripe_subscription_events: Stripe Subscription Events
|
14
|
+
manage_plans: Manage Plans
|
15
|
+
no_resource_found: No %{resource} found
|
16
|
+
add_one: Add one
|
17
|
+
edit: Edit
|
18
|
+
messages:
|
19
|
+
success:
|
20
|
+
successfully_subscribed: Successfully subscribed
|
21
|
+
successfully_unsubscribed: Successfully unsubscribed
|
22
|
+
successfully_canceled_renewal: Successfully canceled renewal
|
23
|
+
successfully_upgraded: Successfully Upgraded
|
24
|
+
successfully_downgraded: Successfully Downgraded
|
25
|
+
successfully_updated: Successfully Updated
|
26
|
+
errors:
|
27
|
+
no_active_subscription: You don't have any active subscription
|
28
|
+
already_subscribed: You already have active subscription
|
29
|
+
stripe_configuration_doesnt_exist: Stripe configurations not found
|
30
|
+
cannot_process_request: Please contact us to proceed
|
31
|
+
models:
|
32
|
+
stripe_configuration:
|
33
|
+
name: Name
|
34
|
+
description: Description
|
35
|
+
active: Active
|
36
|
+
deleted_at: Deleted At
|
37
|
+
billing_address_collection: Billing Address Collection
|
38
|
+
automatic_tax: Automatic Tax
|
39
|
+
tax_id_collection: Tax ID Collection
|
40
|
+
stripe_customers:
|
41
|
+
name: Name
|
42
|
+
email: Email
|
43
|
+
stripe_customer_id: Stripe Customer ID
|
44
|
+
deleted_at: Deleted At
|
45
|
+
stripe_plans:
|
46
|
+
name: Name
|
47
|
+
description: Description
|
48
|
+
currency: Currency
|
49
|
+
amount: Amount
|
50
|
+
interval: Interval
|
51
|
+
interval_count: Interval Count
|
52
|
+
trial_period_days: Trial Period Days
|
53
|
+
configuration_id: Configuration ID
|
54
|
+
stripe_plan_id: Stripe Plan ID
|
55
|
+
active: Active
|
56
|
+
deleted_at: Deleted At
|
57
|
+
weightage: Plan Weightage
|
58
|
+
weightage_title: Move plans to update weightage, it'll be helpful in setting up upgrades/downgrades
|
59
|
+
tax_behavior: Tax Behavior
|
60
|
+
stripe_subscription_events:
|
61
|
+
event_id: Event ID
|
62
|
+
event_type: Event Type
|
63
|
+
stripe_subscription_id: Stripe Subscription ID
|
64
|
+
stripe_subscriptions:
|
65
|
+
stripe_subscription_id: Stripe Subscription ID
|
66
|
+
plan: Plan
|
67
|
+
user: User
|
68
|
+
customer: Customer
|
69
|
+
status: Status
|
70
|
+
plans: Plans
|
71
|
+
spree:
|
72
|
+
public_key: Public Key
|
73
|
+
secret_key: Secret Key
|
74
|
+
webhook_secret: Webhook Secret Key
|
75
|
+
subscribe: Subscribe
|
76
|
+
unsubscribe: Unsubscribe
|
77
|
+
cancel_renewal: Cancel Renewal
|
78
|
+
upgrade: Upgrade
|
79
|
+
downgrade: Downgrade
|
80
|
+
update_payment_method: Update Payment Method
|
data/config/routes.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Spree::Core::Engine.add_routes do
|
2
|
+
namespace :admin, path: Spree.admin_path do
|
3
|
+
resources :stripe_configurations, except: :show do
|
4
|
+
resources :stripe_plans, except: :show do
|
5
|
+
collection do
|
6
|
+
post :update_positions
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
resources :stripe_customers, only: :index
|
12
|
+
resources :stripe_subscriptions, only: :index
|
13
|
+
resources :stripe_subscription_events, only: :index
|
14
|
+
end
|
15
|
+
|
16
|
+
resources :stripe_plans, only: :index, path: SpreeStripeSubscriptions::Config.stripe_plans_path do
|
17
|
+
resources :stripe_subscriptions, only: %i[create update destroy] do
|
18
|
+
post :downgrade, on: :member
|
19
|
+
post :change_payment_details, on: :member
|
20
|
+
get :update_payment_details, on: :member
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
resources :stripe_webhooks, only: :none, path: SpreeStripeSubscriptions::Config.stripe_webhooks_path do
|
25
|
+
post :handler, on: :collection
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class AddSpreeStripeConfigurationModel < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
create_table :spree_stripe_configurations, if_not_exists: true do |t|
|
4
|
+
t.string :name
|
5
|
+
t.text :description
|
6
|
+
|
7
|
+
t.boolean :active
|
8
|
+
t.text :preferences
|
9
|
+
|
10
|
+
t.datetime :deleted_at
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class AddSpreeStripePlanModel < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
create_table :spree_stripe_plans, if_not_exists: true do |t|
|
4
|
+
t.string :name
|
5
|
+
t.text :description
|
6
|
+
|
7
|
+
t.string :currency
|
8
|
+
t.decimal :amount, precision: 8, scale: 2, null: false, default: 0.0
|
9
|
+
|
10
|
+
t.string :interval
|
11
|
+
t.integer :interval_count, default: 1
|
12
|
+
t.integer :trial_period_days, default: 0
|
13
|
+
|
14
|
+
t.references :configuration
|
15
|
+
t.string :stripe_plan_id, null: false
|
16
|
+
|
17
|
+
t.boolean :active, default: false
|
18
|
+
|
19
|
+
t.datetime :deleted_at
|
20
|
+
t.timestamps
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class AddSpreeStripeSubscriptionModel < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
create_table :spree_stripe_subscriptions, if_not_exists: true do |t|
|
4
|
+
t.references :plan
|
5
|
+
t.references :customer
|
6
|
+
t.references :user
|
7
|
+
|
8
|
+
t.string :stripe_subscription_id
|
9
|
+
|
10
|
+
t.string :status
|
11
|
+
t.datetime :current_period_start
|
12
|
+
t.datetime :current_period_end
|
13
|
+
t.datetime :billing_cycle_anchor
|
14
|
+
t.boolean :cancel_at_period_end, default: false
|
15
|
+
t.datetime :cancel_at
|
16
|
+
t.datetime :canceled_at
|
17
|
+
t.datetime :ended_at
|
18
|
+
|
19
|
+
t.datetime :deleted_at
|
20
|
+
t.timestamps
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class AddSpreeStripeSubscriptionEventsModel < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
create_table :spree_stripe_subscription_events, if_not_exists: true do |t|
|
4
|
+
t.string :event_id
|
5
|
+
t.string :event_type
|
6
|
+
|
7
|
+
t.references :subscription
|
8
|
+
t.references :user
|
9
|
+
|
10
|
+
t.text :response
|
11
|
+
|
12
|
+
t.datetime :deleted_at
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class AddWeightageToStripePlan < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
add_column :spree_stripe_plans, :weightage, :integer, if_not_exists: true
|
4
|
+
|
5
|
+
# Migrate existing stripe plans
|
6
|
+
Spree::StripePlan.with_deleted.order(:updated_at).each.with_index(1) do |stripe_plan, index|
|
7
|
+
stripe_plan.update_column :weightage, index
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class AddStripeInvoices < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
create_table :spree_stripe_invoices, if_not_exists: true do |t|
|
4
|
+
t.references :customer
|
5
|
+
t.references :subscription
|
6
|
+
|
7
|
+
t.string :stripe_invoice_id
|
8
|
+
|
9
|
+
t.string :status
|
10
|
+
t.boolean :paid, default: false
|
11
|
+
t.string :currency
|
12
|
+
|
13
|
+
t.decimal :amount_paid, precision: 8, scale: 2, null: false, default: 0.0
|
14
|
+
t.decimal :subtotal, precision: 8, scale: 2, null: false, default: 0.0
|
15
|
+
t.decimal :subtotal_excluding_tax, precision: 8, scale: 2, null: false, default: 0.0
|
16
|
+
t.decimal :tax, precision: 8, scale: 2, null: false, default: 0.0
|
17
|
+
t.decimal :total, precision: 8, scale: 2, null: false, default: 0.0
|
18
|
+
t.decimal :total_excluding_tax, precision: 8, scale: 2, null: false, default: 0.0
|
19
|
+
|
20
|
+
t.string :customer_name
|
21
|
+
t.string :billing_reason
|
22
|
+
t.string :invoice_pdf
|
23
|
+
|
24
|
+
t.datetime :period_start
|
25
|
+
t.datetime :period_end
|
26
|
+
|
27
|
+
t.text :raw_data
|
28
|
+
|
29
|
+
t.datetime :deleted_at
|
30
|
+
t.timestamps
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class AddExtraPlanFields < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
add_column :spree_stripe_plans, :tax_behavior, :string, default: 'unspecified'
|
4
|
+
add_column :spree_stripe_configurations, :automatic_tax, :boolean, default: true
|
5
|
+
add_column :spree_stripe_configurations, :billing_address_collection, :string
|
6
|
+
add_column :spree_stripe_configurations, :tax_id_collection, :boolean, default: true
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SpreeStripeSubscriptions
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
class_option :migrate, type: :boolean, default: true
|
5
|
+
|
6
|
+
def add_migrations
|
7
|
+
run 'bundle exec rake railties:install:migrations FROM=spree_stripe_subscriptions'
|
8
|
+
end
|
9
|
+
|
10
|
+
def run_migrations
|
11
|
+
run_migrations = options[:migrate] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
|
12
|
+
if run_migrations
|
13
|
+
run 'bundle exec rails db:migrate'
|
14
|
+
else
|
15
|
+
puts 'Skipping rails db:migrate, don\'t forget to run it!'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SpreeStripeSubscriptions
|
2
|
+
class Engine < Rails::Engine
|
3
|
+
require 'spree/core'
|
4
|
+
isolate_namespace Spree
|
5
|
+
engine_name 'spree_stripe_subscriptions'
|
6
|
+
|
7
|
+
# use rspec for tests
|
8
|
+
config.generators do |g|
|
9
|
+
g.test_framework :rspec
|
10
|
+
end
|
11
|
+
|
12
|
+
initializer 'spree_stripe_subscriptions.environment', before: :load_config_initializers do |_app|
|
13
|
+
SpreeStripeSubscriptions::Config = SpreeStripeSubscriptions::Configuration.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.activate
|
17
|
+
Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')).sort.each do |c|
|
18
|
+
Rails.configuration.cache_classes ? require(c) : load(c)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
config.to_prepare(&method(:activate).to_proc)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
FactoryBot.define do
|
2
|
+
# Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them.
|
3
|
+
#
|
4
|
+
# Example adding this to your spec_helper will load these Factories for use:
|
5
|
+
# require 'spree_stripe_subscriptions/factories'
|
6
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
require 'spree_stripe_subscriptions/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.name = 'spree_stripe_subscriptions'
|
10
|
+
s.version = SpreeStripeSubscriptions.version
|
11
|
+
s.summary = 'Spree extension to manage stripe subscriptions using Stripe Checkout Session.'
|
12
|
+
s.description = s.summary
|
13
|
+
s.required_ruby_version = '>= 2.5'
|
14
|
+
|
15
|
+
s.author = 'Satyakam Pandya'
|
16
|
+
s.email = 'satyakampandya@gmail.com'
|
17
|
+
s.homepage = 'https://github.com/satyakampandya/spree_stripe_subscriptions'
|
18
|
+
s.license = 'BSD-3-Clause'
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n").reject { |f| f.match(/^spec/) && !f.match(/^spec\/fixtures/) }
|
21
|
+
s.require_path = 'lib'
|
22
|
+
s.requirements << 'none'
|
23
|
+
|
24
|
+
s.add_dependency 'spree', '>= 4.3.0'
|
25
|
+
s.add_dependency 'spree_backend'
|
26
|
+
s.add_dependency 'spree_extension'
|
27
|
+
|
28
|
+
s.add_dependency 'stripe', '>= 3.3.2', '< 8.0.0'
|
29
|
+
s.add_dependency 'stripe_tester'
|
30
|
+
|
31
|
+
s.add_dependency 'deface', '~> 1.0'
|
32
|
+
|
33
|
+
s.add_development_dependency 'spree_dev_tools'
|
34
|
+
end
|