solidus_subscriptions 1.0.0.rc1

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.
Files changed (204) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +41 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +17 -0
  5. data/.github_changelog_generator +2 -0
  6. data/.gitignore +20 -0
  7. data/.rspec +2 -0
  8. data/.rubocop.yml +12 -0
  9. data/.rubocop_todo.yml +86 -0
  10. data/CHANGELOG.md +191 -0
  11. data/Gemfile +33 -0
  12. data/LICENSE +26 -0
  13. data/README.md +221 -0
  14. data/Rakefile +6 -0
  15. data/app/assets/javascripts/spree/backend/solidus_subscriptions.js +1 -0
  16. data/app/assets/javascripts/spree/backend/solidus_subscriptions/edit_subscription_payment.js +32 -0
  17. data/app/controllers/solidus_subscriptions/api/v1/base_controller.rb +13 -0
  18. data/app/controllers/solidus_subscriptions/api/v1/line_items_controller.rb +48 -0
  19. data/app/controllers/solidus_subscriptions/api/v1/subscriptions_controller.rb +100 -0
  20. data/app/controllers/spree/admin/installments_controller.rb +25 -0
  21. data/app/controllers/spree/admin/subscription_events_controller.rb +37 -0
  22. data/app/controllers/spree/admin/subscription_orders_controller.rb +35 -0
  23. data/app/controllers/spree/admin/subscriptions_controller.rb +100 -0
  24. data/app/controllers/spree/admin/users/subscriptions_controller.rb +17 -0
  25. data/app/decorators/controllers/solidus_subscriptions/spree/api/line_items_controller/create_subscription_line_items.rb +36 -0
  26. data/app/decorators/controllers/solidus_subscriptions/spree/orders_controller/create_subscription_line_items.rb +35 -0
  27. data/app/decorators/models/solidus_subscriptions/spree/line_item/subscription_line_items_association.rb +26 -0
  28. data/app/decorators/models/solidus_subscriptions/spree/order/after_create.rb +19 -0
  29. data/app/decorators/models/solidus_subscriptions/spree/order/finalize_creates_subscriptions.rb +23 -0
  30. data/app/decorators/models/solidus_subscriptions/spree/order/installment_details_association.rb +15 -0
  31. data/app/decorators/models/solidus_subscriptions/spree/order/subscription_association.rb +15 -0
  32. data/app/decorators/models/solidus_subscriptions/spree/order/subscription_line_items_association.rb +19 -0
  33. data/app/decorators/models/solidus_subscriptions/spree/product/delegate_subscribable.rb +17 -0
  34. data/app/decorators/models/solidus_subscriptions/spree/user/have_many_subscriptions.rb +30 -0
  35. data/app/decorators/models/solidus_subscriptions/spree/variant/auto_delete_from_subscriptions.rb +20 -0
  36. data/app/decorators/models/solidus_subscriptions/spree/variant/variant_pretty_name.rb +17 -0
  37. data/app/decorators/models/solidus_subscriptions/spree/wallet_payment_source/report_default_change_to_subscriptions.rb +28 -0
  38. data/app/jobs/solidus_subscriptions/process_installment_job.rb +13 -0
  39. data/app/jobs/solidus_subscriptions/process_subscription_job.rb +31 -0
  40. data/app/models/solidus_subscriptions/installment.rb +135 -0
  41. data/app/models/solidus_subscriptions/installment_detail.rb +28 -0
  42. data/app/models/solidus_subscriptions/interval.rb +26 -0
  43. data/app/models/solidus_subscriptions/line_item.rb +42 -0
  44. data/app/models/solidus_subscriptions/promotion/rules/subscription_creation_order.rb +44 -0
  45. data/app/models/solidus_subscriptions/promotion/rules/subscription_installment_order.rb +31 -0
  46. data/app/models/solidus_subscriptions/subscription.rb +392 -0
  47. data/app/models/solidus_subscriptions/subscription_event.rb +11 -0
  48. data/app/overrides/views/admin_subscribable_product_checkbox.rb +8 -0
  49. data/app/overrides/views/admin_subscribable_variant_checkbox.rb +8 -0
  50. data/app/overrides/views/admin_subscriptions_menu_link.rb +10 -0
  51. data/app/overrides/views/admin_users_subscriptions_tab.rb +8 -0
  52. data/app/overrides/views/subscription_line_item_fields.rb +8 -0
  53. data/app/subscribers/solidus_subscriptions/churn_buster_subscriber.rb +39 -0
  54. data/app/subscribers/solidus_subscriptions/event_storage_subscriber.rb +64 -0
  55. data/app/views/spree/admin/installments/_state_pill.html.erb +8 -0
  56. data/app/views/spree/admin/installments/index.html.erb +42 -0
  57. data/app/views/spree/admin/products/_subscribable_checkbox.html.erb +8 -0
  58. data/app/views/spree/admin/promotions/rules/_subscription_creation_order.html.erb +0 -0
  59. data/app/views/spree/admin/promotions/rules/_subscription_installment_order.html.erb +0 -0
  60. data/app/views/spree/admin/shared/_subscription_actions.html.erb +35 -0
  61. data/app/views/spree/admin/shared/_subscription_breadcrumbs.html.erb +4 -0
  62. data/app/views/spree/admin/shared/_subscription_sidebar.html.erb +18 -0
  63. data/app/views/spree/admin/shared/_subscription_tab.html.erb +3 -0
  64. data/app/views/spree/admin/shared/_subscription_tabs.html.erb +18 -0
  65. data/app/views/spree/admin/subscription_events/_state_pill.html.erb +8 -0
  66. data/app/views/spree/admin/subscription_events/index.html.erb +42 -0
  67. data/app/views/spree/admin/subscription_orders/index.html.erb +93 -0
  68. data/app/views/spree/admin/subscriptions/_form.html.erb +150 -0
  69. data/app/views/spree/admin/subscriptions/_processing_state_pill.html.erb +9 -0
  70. data/app/views/spree/admin/subscriptions/_state_pill.html.erb +10 -0
  71. data/app/views/spree/admin/subscriptions/edit.html.erb +10 -0
  72. data/app/views/spree/admin/subscriptions/index.html.erb +176 -0
  73. data/app/views/spree/admin/subscriptions/new.html.erb +5 -0
  74. data/app/views/spree/admin/users/_subscription_tab.html.erb +5 -0
  75. data/app/views/spree/admin/users/subscriptions/index.html.erb +44 -0
  76. data/app/views/spree/admin/variants/_subscribable_checkbox.html.erb +6 -0
  77. data/app/views/spree/frontend/products/_subscription_line_item_fields.html.erb +30 -0
  78. data/bin/console +17 -0
  79. data/bin/rails +7 -0
  80. data/bin/rails-engine +13 -0
  81. data/bin/rails-sandbox +16 -0
  82. data/bin/rake +7 -0
  83. data/bin/sandbox +86 -0
  84. data/bin/setup +8 -0
  85. data/config/initializers/permission_sets.rb +11 -0
  86. data/config/initializers/subscribers.rb +9 -0
  87. data/config/locales/en.yml +129 -0
  88. data/config/routes.rb +34 -0
  89. data/db/migrate/20160825164850_create_solidus_subscriptions_subscriptions.rb +11 -0
  90. data/db/migrate/20160825173548_create_solidus_subscriptions_line_items.rb +17 -0
  91. data/db/migrate/20160825202248_create_solidus_subscriptions_installments.rb +23 -0
  92. data/db/migrate/20160825211202_create_solidus_subscriptions_installment_details.rb +22 -0
  93. data/db/migrate/20160825214240_add_subscribable_to_spree_variants.rb +5 -0
  94. data/db/migrate/20160829201653_change_subscription_line_items_installments_to_max_installments.rb +5 -0
  95. data/db/migrate/20160902220242_remove_state_from_solidus_susbscriptions_installment_details.rb +5 -0
  96. data/db/migrate/20160902220604_add_successful_to_solidus_subscriptions_installment_details.rb +5 -0
  97. data/db/migrate/20160902221218_add_message_to_solidus_subscriptions_installment_details.rb +5 -0
  98. data/db/migrate/20160922164101_add_interval_length_and_units_to_subscription_line_items.rb +8 -0
  99. data/db/migrate/20161006191003_add_skip_count_to_solidus_subscriptions_subscriptions.rb +5 -0
  100. data/db/migrate/20161006191127_add_successive_skip_count_to_solidus_subscriptions_subscriptions.rb +5 -0
  101. data/db/migrate/20161014212649_allow_spree_line_item_id_to_be_null.rb +5 -0
  102. data/db/migrate/20161017155749_add_order_id_to_solidus_subscriptions_installment_details.rb +6 -0
  103. data/db/migrate/20161017175509_remove_order_id_from_solidus_subscriptions_installments.rb +5 -0
  104. data/db/migrate/20161017201944_add_subscription_order_to_spree_orders.rb +5 -0
  105. data/db/migrate/20161221155142_add_store_to_solidus_subscriptions_subscriptions.rb +6 -0
  106. data/db/migrate/20161223152905_add_address_id_to_solidus_subscriptions_subscriptions.rb +7 -0
  107. data/db/migrate/20170106224713_change_line_item_max_installments_to_end_date.rb +6 -0
  108. data/db/migrate/20170111224458_change_subscription_actionable_date_to_datetime.rb +5 -0
  109. data/db/migrate/20170111232801_change_inteval_actionable_date_to_datetime.rb +5 -0
  110. data/db/migrate/20170112012407_add_config_options_to_subscriptions.rb +7 -0
  111. data/db/migrate/20200617102749_add_billing_address_to_subscriptions.rb +11 -0
  112. data/db/migrate/20200617155042_add_payment_source_to_subscriptions.rb +6 -0
  113. data/db/migrate/20200618092951_add_payment_method_to_subscriptions.rb +11 -0
  114. data/db/migrate/20200730101242_create_solidus_subscriptions_subscription_events.rb +22 -0
  115. data/db/migrate/20200917072152_add_subscription_reference_to_orders.rb +11 -0
  116. data/db/migrate/20201007140032_add_guest_token_to_subscriptions.rb +6 -0
  117. data/db/migrate/20201123171026_change_actionable_date_to_date.rb +15 -0
  118. data/db/migrate/20210205140422_add_currency_to_subscription.rb +5 -0
  119. data/db/migrate/20210323165714_update_promotion_rule_names.rb +22 -0
  120. data/lib/generators/solidus_subscriptions/install/install_generator.rb +32 -0
  121. data/lib/generators/solidus_subscriptions/install/templates/initializer.rb +99 -0
  122. data/lib/solidus_subscriptions.rb +49 -0
  123. data/lib/solidus_subscriptions/checkout.rb +74 -0
  124. data/lib/solidus_subscriptions/churn_buster/client.rb +48 -0
  125. data/lib/solidus_subscriptions/churn_buster/order_serializer.rb +19 -0
  126. data/lib/solidus_subscriptions/churn_buster/serializer.rb +23 -0
  127. data/lib/solidus_subscriptions/churn_buster/subscription_customer_serializer.rb +28 -0
  128. data/lib/solidus_subscriptions/churn_buster/subscription_payment_method_serializer.rb +37 -0
  129. data/lib/solidus_subscriptions/churn_buster/subscription_serializer.rb +17 -0
  130. data/lib/solidus_subscriptions/configuration.rb +84 -0
  131. data/lib/solidus_subscriptions/dispatcher/base.rb +18 -0
  132. data/lib/solidus_subscriptions/dispatcher/failure_dispatcher.rb +13 -0
  133. data/lib/solidus_subscriptions/dispatcher/out_of_stock_dispatcher.rb +11 -0
  134. data/lib/solidus_subscriptions/dispatcher/payment_failed_dispatcher.rb +19 -0
  135. data/lib/solidus_subscriptions/dispatcher/success_dispatcher.rb +17 -0
  136. data/lib/solidus_subscriptions/engine.rb +56 -0
  137. data/lib/solidus_subscriptions/permission_sets/default_customer.rb +19 -0
  138. data/lib/solidus_subscriptions/permission_sets/subscription_management.rb +12 -0
  139. data/lib/solidus_subscriptions/permitted_attributes.rb +20 -0
  140. data/lib/solidus_subscriptions/processor.rb +17 -0
  141. data/lib/solidus_subscriptions/subscription_generator.rb +77 -0
  142. data/lib/solidus_subscriptions/subscription_line_item_builder.rb +23 -0
  143. data/lib/solidus_subscriptions/testing_support/factories/installment_detail_factory.rb +11 -0
  144. data/lib/solidus_subscriptions/testing_support/factories/installment_factory.rb +29 -0
  145. data/lib/solidus_subscriptions/testing_support/factories/line_item_factory.rb +20 -0
  146. data/lib/solidus_subscriptions/testing_support/factories/spree/line_item_factory.rb +17 -0
  147. data/lib/solidus_subscriptions/testing_support/factories/spree/order_factory.rb +17 -0
  148. data/lib/solidus_subscriptions/testing_support/factories/spree_modification_factory.rb +10 -0
  149. data/lib/solidus_subscriptions/testing_support/factories/subscription_event_factory.rb +8 -0
  150. data/lib/solidus_subscriptions/testing_support/factories/subscription_factory.rb +56 -0
  151. data/lib/solidus_subscriptions/version.rb +5 -0
  152. data/lib/tasks/process_subscriptions.rake +8 -0
  153. data/reference/solidus_subscriptions.v1.yaml +290 -0
  154. data/solidus_subscriptions.gemspec +47 -0
  155. data/spec/controllers/spree/admin/subscriptions_controller_spec.rb +202 -0
  156. data/spec/controllers/spree/api/line_items_controller_spec.rb +103 -0
  157. data/spec/controllers/spree/api/orders_controller_spec.rb +57 -0
  158. data/spec/controllers/spree/api/users_controller_spec.rb +48 -0
  159. data/spec/decorators/controllers/solidus_subscriptions/spree/orders_controller/create_subscription_line_items_spec.rb +80 -0
  160. data/spec/decorators/models/solidus_subscriptions/spree/line_item/subscription_line_items_association_spec.rb +10 -0
  161. data/spec/decorators/models/solidus_subscriptions/spree/order/finalize_creates_subscriptions_spec.rb +32 -0
  162. data/spec/decorators/models/solidus_subscriptions/spree/order/installment_details_association_spec.rb +9 -0
  163. data/spec/decorators/models/solidus_subscriptions/spree/order/subscription_line_items_association_spec.rb +9 -0
  164. data/spec/decorators/models/solidus_subscriptions/spree/user/have_many_subscriptions_spec.rb +22 -0
  165. data/spec/decorators/models/solidus_subscriptions/spree/variant/auto_delete_from_subscriptions_spec.rb +25 -0
  166. data/spec/features/admin/subscription_orders_spec.rb +35 -0
  167. data/spec/features/admin/subscriptions_spec.rb +63 -0
  168. data/spec/features/admin_users_subscription_tabs_spec.rb +61 -0
  169. data/spec/fixtures/cassettes/churn_buster.yml +229 -0
  170. data/spec/jobs/solidus_subscriptions/process_installment_job_spec.rb +38 -0
  171. data/spec/jobs/solidus_subscriptions/process_subscription_job_spec.rb +83 -0
  172. data/spec/lib/solidus_subscriptions/checkout_spec.rb +125 -0
  173. data/spec/lib/solidus_subscriptions/churn_buster/client_spec.rb +59 -0
  174. data/spec/lib/solidus_subscriptions/dispatcher/failure_dispatcher_spec.rb +29 -0
  175. data/spec/lib/solidus_subscriptions/dispatcher/out_of_stock_dispatcher_spec.rb +15 -0
  176. data/spec/lib/solidus_subscriptions/dispatcher/payment_failed_dispatcher_spec.rb +44 -0
  177. data/spec/lib/solidus_subscriptions/dispatcher/success_dispatcher_spec.rb +30 -0
  178. data/spec/lib/solidus_subscriptions/permission_sets/default_customer_spec.rb +95 -0
  179. data/spec/lib/solidus_subscriptions/permission_sets/subscription_management_spec.rb +26 -0
  180. data/spec/lib/solidus_subscriptions/processor_spec.rb +34 -0
  181. data/spec/lib/solidus_subscriptions/promotion/rules/subscription_creation_order_spec.rb +57 -0
  182. data/spec/lib/solidus_subscriptions/promotion/rules/subscription_installment_order_spec.rb +39 -0
  183. data/spec/lib/solidus_subscriptions/subscription_generator_spec.rb +83 -0
  184. data/spec/lib/solidus_subscriptions_spec.rb +30 -0
  185. data/spec/models/solidus_subscriptions/installment_detail_spec.rb +23 -0
  186. data/spec/models/solidus_subscriptions/installment_spec.rb +201 -0
  187. data/spec/models/solidus_subscriptions/line_item_spec.rb +29 -0
  188. data/spec/models/solidus_subscriptions/subscription_spec.rb +814 -0
  189. data/spec/models/spree/variant_spec.rb +16 -0
  190. data/spec/models/spree/wallet_payment_source_spec.rb +20 -0
  191. data/spec/requests/api/v1/line_items_spec.rb +116 -0
  192. data/spec/requests/api/v1/subscriptions_spec.rb +255 -0
  193. data/spec/spec_helper.rb +30 -0
  194. data/spec/subscribers/solidus_subscriptions/churn_buster_subscriber_spec.rb +76 -0
  195. data/spec/support/active_model_mocks.rb +1 -0
  196. data/spec/support/cancancan.rb +1 -0
  197. data/spec/support/factories.rb +1 -0
  198. data/spec/support/helpers/checkout_infrastructure.rb +18 -0
  199. data/spec/support/helpers/config.rb +13 -0
  200. data/spec/support/shoulda.rb +7 -0
  201. data/spec/support/timecop.rb +1 -0
  202. data/spec/support/vcr.rb +10 -0
  203. data/spec/support/version_cake.rb +8 -0
  204. metadata +498 -0
@@ -0,0 +1,5 @@
1
+ class RemoveStateFromSolidusSusbscriptionsInstallmentDetails < SolidusSupport::Migration[4.2]
2
+ def change
3
+ remove_column :solidus_subscriptions_installment_details, :state, :string
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddSuccessfulToSolidusSubscriptionsInstallmentDetails < SolidusSupport::Migration[4.2]
2
+ def change
3
+ add_column :solidus_subscriptions_installment_details, :success, :boolean
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddMessageToSolidusSubscriptionsInstallmentDetails < SolidusSupport::Migration[4.2]
2
+ def change
3
+ add_column :solidus_subscriptions_installment_details, :message, :string
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ class AddIntervalLengthAndUnitsToSubscriptionLineItems < SolidusSupport::Migration[4.2]
2
+ def change
3
+ add_column :solidus_subscriptions_line_items, :interval_units, :integer
4
+ add_column :solidus_subscriptions_line_items, :interval_length, :integer
5
+
6
+ remove_column :solidus_subscriptions_line_items, :interval
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ class AddSkipCountToSolidusSubscriptionsSubscriptions < SolidusSupport::Migration[4.2]
2
+ def change
3
+ add_column :solidus_subscriptions_subscriptions, :skip_count, :integer, default: 0, null: false
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddSuccessiveSkipCountToSolidusSubscriptionsSubscriptions < SolidusSupport::Migration[4.2]
2
+ def change
3
+ add_column :solidus_subscriptions_subscriptions, :successive_skip_count, :integer, default: 0, null: false
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AllowSpreeLineItemIdToBeNull < SolidusSupport::Migration[4.2]
2
+ def change
3
+ change_column_null :solidus_subscriptions_line_items, :spree_line_item_id, true
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class AddOrderIdToSolidusSubscriptionsInstallmentDetails < SolidusSupport::Migration[4.2]
2
+ def change
3
+ add_reference :solidus_subscriptions_installment_details, :order, index: true
4
+ add_foreign_key :solidus_subscriptions_installment_details, :spree_orders, column: :order_id
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class RemoveOrderIdFromSolidusSubscriptionsInstallments < SolidusSupport::Migration[4.2]
2
+ def change
3
+ remove_column :solidus_subscriptions_installments, :order_id, :integer
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddSubscriptionOrderToSpreeOrders < SolidusSupport::Migration[4.2]
2
+ def change
3
+ add_column :spree_orders, :subscription_order, :boolean, default: false, null: false
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class AddStoreToSolidusSubscriptionsSubscriptions < SolidusSupport::Migration[4.2]
2
+ def change
3
+ add_reference :solidus_subscriptions_subscriptions, :store, index: true
4
+ add_foreign_key :solidus_subscriptions_subscriptions, :spree_stores, column: :store_id
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ class AddAddressIdToSolidusSubscriptionsSubscriptions < SolidusSupport::Migration[4.2]
2
+ def change
3
+ add_reference :solidus_subscriptions_subscriptions, :shipping_address
4
+ add_index :solidus_subscriptions_subscriptions, :shipping_address_id, name: :index_subscription_shipping_address_id
5
+ add_foreign_key :solidus_subscriptions_subscriptions, :spree_addresses, column: :shipping_address_id
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ class ChangeLineItemMaxInstallmentsToEndDate < SolidusSupport::Migration[4.2]
2
+ def change
3
+ remove_column :solidus_subscriptions_line_items, :max_installments
4
+ add_column :solidus_subscriptions_line_items, :end_date, :date
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class ChangeSubscriptionActionableDateToDatetime < SolidusSupport::Migration[4.2]
2
+ def change
3
+ change_column :solidus_subscriptions_subscriptions, :actionable_date, :datetime
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class ChangeIntevalActionableDateToDatetime < SolidusSupport::Migration[4.2]
2
+ def change
3
+ change_column :solidus_subscriptions_installments, :actionable_date, :datetime
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class AddConfigOptionsToSubscriptions < SolidusSupport::Migration[4.2]
2
+ def change
3
+ add_column :solidus_subscriptions_subscriptions, :interval_length, :integer
4
+ add_column :solidus_subscriptions_subscriptions, :interval_units, :integer
5
+ add_column :solidus_subscriptions_subscriptions, :end_date, :datetime
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ class AddBillingAddressToSubscriptions < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_reference(
4
+ :solidus_subscriptions_subscriptions,
5
+ :billing_address,
6
+ type: :integer,
7
+ index: { name: :index_subscription_billing_address_id },
8
+ foreign_key: { to_table: :spree_addresses }
9
+ )
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ class AddPaymentSourceToSubscriptions < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_column :solidus_subscriptions_subscriptions, :payment_source_type, :string
4
+ add_column :solidus_subscriptions_subscriptions, :payment_source_id, :integer
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ class AddPaymentMethodToSubscriptions < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_reference(
4
+ :solidus_subscriptions_subscriptions,
5
+ :payment_method,
6
+ type: :integer,
7
+ index: { name: :index_subscription_payment_method_id },
8
+ foreign_key: { to_table: :spree_payment_methods }
9
+ )
10
+ end
11
+ end
@@ -0,0 +1,22 @@
1
+ class CreateSolidusSubscriptionsSubscriptionEvents < ActiveRecord::Migration[5.2]
2
+ def change
3
+ create_table :solidus_subscriptions_subscription_events do |t|
4
+ t.belongs_to(
5
+ :subscription,
6
+ null: false,
7
+ foreign_key: { to_table: :solidus_subscriptions_subscriptions },
8
+ index: { name: :idx_solidus_subscription_events_on_subscription_id },
9
+ type: :integer,
10
+ )
11
+ t.string :event_type, null: false
12
+
13
+ if t.respond_to?(:jsonb)
14
+ t.jsonb :details, null: false
15
+ else
16
+ t.json :details, null: false
17
+ end
18
+
19
+ t.timestamps
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ class AddSubscriptionReferenceToOrders < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_reference(
4
+ :spree_orders,
5
+ :subscription,
6
+ null: true,
7
+ type: :integer,
8
+ foreign_key: { to_table: :solidus_subscriptions_subscriptions }
9
+ )
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ class AddGuestTokenToSubscriptions < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_column :solidus_subscriptions_subscriptions, :guest_token, :string
4
+ add_index :solidus_subscriptions_subscriptions, :guest_token, unique: true
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ class ChangeActionableDateToDate < ActiveRecord::Migration[5.2]
2
+ def change
3
+ reversible do |dir|
4
+ dir.up do
5
+ change_column :solidus_subscriptions_subscriptions, :actionable_date, :date
6
+ change_column :solidus_subscriptions_installments, :actionable_date, :date
7
+ end
8
+
9
+ dir.down do
10
+ change_column :solidus_subscriptions_subscriptions, :actionable_date, :datetime
11
+ change_column :solidus_subscriptions_installments, :actionable_date, :datetime
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ class AddCurrencyToSubscription < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_column :solidus_subscriptions_subscriptions, :currency, :string
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ class UpdatePromotionRuleNames < ActiveRecord::Migration[5.2]
2
+ TYPE_RENAMES = {
3
+ 'SolidusSubscriptions::SubscriptionPromotionRule' => 'SolidusSubscriptions::Promotion::Rules::SubscriptionCreationOrder',
4
+ 'SolidusSubscriptions::SubscriptionOrderPromotionRule' => 'SolidusSubscriptions::Promotion::Rules::SubscriptionInstallmentOrder',
5
+ }.freeze
6
+
7
+ def change
8
+ reversible do |dir|
9
+ dir.up do
10
+ TYPE_RENAMES.each do |old_type, new_type|
11
+ Spree::PromotionRule.where(type: old_type).update(type: new_type)
12
+ end
13
+ end
14
+
15
+ dir.down do
16
+ TYPE_RENAMES.each do |old_type, new_type|
17
+ Spree::PromotionRule.where(type: new_type).update(type: old_type)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusSubscriptions
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path('templates', __dir__)
7
+
8
+ class_option :auto_run_migrations, type: :boolean, default: false
9
+
10
+ def copy_initializer
11
+ template 'initializer.rb', 'config/initializers/solidus_subscriptions.rb'
12
+ end
13
+
14
+ def add_javascripts
15
+ append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/solidus_subscriptions\n"
16
+ end
17
+
18
+ def add_migrations
19
+ run 'bin/rails railties:install:migrations FROM=solidus_subscriptions'
20
+ end
21
+
22
+ def run_migrations
23
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
24
+ if run_migrations
25
+ run 'bin/rails db:migrate'
26
+ else
27
+ puts 'Skipping bin/rails db:migrate, don\'t forget to run it!' # rubocop:disable Rails/Output
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ SolidusSubscriptions.configure do |config|
4
+ # ========================================= Basic config =========================================
5
+
6
+ # The ActiveRecord model users can subscribe to.
7
+ # config.subscribable_class = 'Spree::Variant'
8
+
9
+ # Which queue is responsible for processing subscription background jobs.
10
+ # config.processing_queue = :default
11
+
12
+ # Maximum number of times a user can skip their subscription before it must be processed.
13
+ # config.maximum_successive_skips = 1
14
+
15
+ # Maximum number of times a user can skip their subscription.
16
+ # config.maximum_total_skips = nil
17
+
18
+ # Minimum days between the current date and the next installment for the installment not to be
19
+ # processed after the user cancels their subscription.
20
+ # config.minimum_cancellation_notice = 1.day
21
+
22
+ # Time between an installment failing to be processed and the system retrying to fulfill it.
23
+ # config.reprocessing_interval = 1.day
24
+
25
+ # Maximum time that can pass after the last succesfull subscription installment to make a payment
26
+ # failure cancel the subscription.
27
+ # config.maximum_reprocessing_time = nil
28
+
29
+ # This custom error handler is called when a ProcessInstallmentJob `#perform` method fails.
30
+ # The rescued error can be managed as required via a Proc, such as one which logs the error
31
+ # on an error tracking system.
32
+ # Though not recommended due to the retry mechanisms built into this gem, the error can be
33
+ # re-raised if the default retry behaviour is required in ActiveJob.
34
+ # config.processing_error_handler = nil
35
+
36
+ # ========================================= Dispatchers ==========================================
37
+ #
38
+ # These dispatchers are pluggable. If you override any handlers, it is highly encouraged that you
39
+ # subclass from the the dispatcher you are replacing and call `super` from within `#dispatch`.
40
+
41
+ # This handler is called when a subscription order is successfully placed.
42
+ # config.success_dispatcher_class = 'SolidusSubscriptions::Dispatcher::SuccessDispatcher'
43
+
44
+ # This handler is called when a group of installments fails to be processed.
45
+ # config.failure_dispatcher_class = 'SolidusSubscriptions::Dispatcher::FailureDispatcher'
46
+
47
+ # This handler is called when a payment fails on a subscription order.
48
+ # config.payment_failed_dispatcher_class = 'SolidusSubscriptions::Dispatcher::PaymentFailedDispatcher'
49
+
50
+ # This handler is called when there isn't enough stock to fulfill an installment.
51
+ # config.out_of_stock_dispatcher = 'SolidusSubscriptions::Dispatcher::OutOfStockDispatcher'
52
+
53
+ # ===================================== Permitted attributes =====================================
54
+ #
55
+ # In this section, you can override the list of attributes the user can pass to the controllers.
56
+ #
57
+ # This is useful in the case where certain fields should not be allowed to be modified by the
58
+ # user, or if you add additional fields to the extension's model and you want the users to be able
59
+ # to set them.
60
+
61
+ # Attributes the user can specify for subscriptions.
62
+ # config.subscription_attributes = [
63
+ # :interval_length,
64
+ # :interval_units,
65
+ # :end_date,
66
+ # shipping_address_attributes: Spree::PermittedAttributes.address_attributes,
67
+ # billing_address_attributes: Spree::PermittedAttributes.address_attributes,
68
+ # ]
69
+
70
+ # Attributes the user be specify for subscription line items.
71
+ # config.subscription_line_item_attributes = [
72
+ # :quantity,
73
+ # :subscribable_id,
74
+ # :interval_length,
75
+ # :interval_units,
76
+ # :end_date,
77
+ # ]
78
+
79
+ # ========================================= Churn Buster =========================================
80
+ #
81
+ # This extension can integrate with Churn Buster for churn mitigation and failed payment recovery.
82
+ # If you want to integrate with Churn Buster, simply configure your credentials below.
83
+ #
84
+ # NOTE: If you integrate with Churn Buster and override any of the handlers, make sure to call
85
+ # `super` or copy-paste the original integration code or things won't work!
86
+
87
+ # Your Churn Buster account ID.
88
+ # config.churn_buster_account_id = 'YOUR_CHURN_BUSTER_ACCOUNT_ID'
89
+
90
+ # Your Churn Buster API key.
91
+ # config.churn_buster_api_key = 'YOUR_CHURN_BUSTER_API_KEY'
92
+
93
+ # =================================== Clear past installments ====================================
94
+ #
95
+ # This setting prevents the overlap of old failed installments (e.g. for an expired credit card)
96
+ # with new subscription cycles by clearing any past failed installment when a new one is created
97
+
98
+ # config.clear_past_installments = true
99
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'solidus_core'
4
+ require 'solidus_support'
5
+
6
+ require 'deface'
7
+ require 'httparty'
8
+ require 'state_machines'
9
+
10
+ require 'solidus_subscriptions/configuration'
11
+ require 'solidus_subscriptions/permission_sets/default_customer'
12
+ require 'solidus_subscriptions/permission_sets/subscription_management'
13
+ require 'solidus_subscriptions/version'
14
+ require 'solidus_subscriptions/engine'
15
+ require 'solidus_subscriptions/churn_buster/client'
16
+ require 'solidus_subscriptions/churn_buster/serializer'
17
+ require 'solidus_subscriptions/churn_buster/subscription_customer_serializer'
18
+ require 'solidus_subscriptions/churn_buster/subscription_payment_method_serializer'
19
+ require 'solidus_subscriptions/churn_buster/subscription_serializer'
20
+ require 'solidus_subscriptions/churn_buster/order_serializer'
21
+ require 'solidus_subscriptions/checkout'
22
+ require 'solidus_subscriptions/subscription_generator'
23
+ require 'solidus_subscriptions/subscription_line_item_builder'
24
+ require 'solidus_subscriptions/dispatcher/base'
25
+ require 'solidus_subscriptions/dispatcher/failure_dispatcher'
26
+ require 'solidus_subscriptions/dispatcher/out_of_stock_dispatcher'
27
+ require 'solidus_subscriptions/dispatcher/payment_failed_dispatcher'
28
+ require 'solidus_subscriptions/dispatcher/success_dispatcher'
29
+
30
+ module SolidusSubscriptions
31
+ class << self
32
+ def configure
33
+ yield configuration
34
+ end
35
+
36
+ def configuration
37
+ @configuration ||= Configuration.new
38
+ end
39
+
40
+ def churn_buster
41
+ return unless configuration.churn_buster?
42
+
43
+ @churn_buster ||= ChurnBuster::Client.new(
44
+ account_id: SolidusSubscriptions.configuration.churn_buster_account_id,
45
+ api_key: SolidusSubscriptions.configuration.churn_buster_api_key,
46
+ )
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusSubscriptions
4
+ class Checkout
5
+ attr_reader :installment
6
+
7
+ def initialize(installment)
8
+ @installment = installment
9
+ end
10
+
11
+ def process
12
+ order = create_order
13
+
14
+ begin
15
+ populate_order(order)
16
+ finalize_order(order)
17
+
18
+ SolidusSubscriptions.configuration.success_dispatcher_class.new(installment, order).dispatch
19
+ rescue StateMachines::InvalidTransition
20
+ if order.payments.any?(&:failed?)
21
+ SolidusSubscriptions.configuration.payment_failed_dispatcher_class.new(installment, order).dispatch
22
+ else
23
+ SolidusSubscriptions.configuration.failure_dispatcher_class.new(installment, order).dispatch
24
+ end
25
+ rescue ::Spree::Order::InsufficientStock
26
+ SolidusSubscriptions.configuration.out_of_stock_dispatcher_class.new(installment, order).dispatch
27
+ end
28
+
29
+ order
30
+ end
31
+
32
+ private
33
+
34
+ def create_order
35
+ ::Spree::Order.create(
36
+ user: installment.subscription.user,
37
+ email: installment.subscription.user.email,
38
+ store: installment.subscription.store || ::Spree::Store.default,
39
+ subscription_order: true,
40
+ subscription: installment.subscription,
41
+ currency: installment.subscription.currency
42
+ )
43
+ end
44
+
45
+ def populate_order(order)
46
+ installment.subscription.line_items.each do |line_item|
47
+ order.contents.add(line_item.subscribable, line_item.quantity)
48
+ end
49
+ end
50
+
51
+ def finalize_order(order)
52
+ ::Spree::PromotionHandler::Cart.new(order).activate
53
+ order.recalculate
54
+
55
+ order.checkout_steps[0...-1].each do
56
+ case order.state
57
+ when 'address'
58
+ order.ship_address = installment.subscription.shipping_address_to_use
59
+ order.bill_address = installment.subscription.billing_address_to_use
60
+ when 'payment'
61
+ order.payments.create(
62
+ payment_method: installment.subscription.payment_method_to_use,
63
+ source: installment.subscription.payment_source_to_use,
64
+ amount: order.total,
65
+ )
66
+ end
67
+
68
+ order.next!
69
+ end
70
+
71
+ order.complete!
72
+ end
73
+ end
74
+ end