solidus_subscriptions 1.0.0 → 1.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 +4 -4
- data/.circleci/config.yml +57 -9
- data/.github/dependabot.yml +7 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +201 -169
- data/Gemfile +14 -1
- data/README.md +17 -7
- data/app/controllers/solidus_subscriptions/api/v1/subscriptions_controller.rb +24 -0
- data/app/controllers/spree/admin/subscriptions_controller.rb +32 -4
- data/app/decorators/models/solidus_subscriptions/spree/wallet_payment_source/report_default_change_to_subscriptions.rb +2 -2
- data/app/jobs/solidus_subscriptions/create_subscription_job.rb +11 -0
- data/app/jobs/solidus_subscriptions/process_installment_job.rb +1 -1
- data/app/models/solidus_subscriptions/subscription.rb +75 -31
- data/app/subscribers/solidus_subscriptions/churn_buster_subscriber.rb +1 -0
- data/app/subscribers/solidus_subscriptions/event_storage_subscriber.rb +1 -0
- data/app/subscribers/solidus_subscriptions/order_subscriber.rb +16 -0
- data/app/views/spree/admin/shared/_subscription_actions.html.erb +27 -8
- data/app/views/spree/admin/shared/_subscription_sidebar.html.erb +2 -0
- data/app/views/spree/admin/subscriptions/_state_pill.html.erb +3 -2
- data/app/views/spree/admin/subscriptions/index.html.erb +50 -13
- data/bin/sandbox +1 -6
- data/config/locales/en.yml +16 -0
- data/config/routes.rb +9 -3
- data/db/migrate/20210905145955_add_paused_to_subscriptions.rb +5 -0
- data/lib/decorators/api/controllers/solidus_subscriptions/spree/api/line_items_controller/create_subscription_line_items.rb +14 -0
- data/lib/generators/solidus_subscriptions/install/install_generator.rb +16 -0
- data/lib/generators/solidus_subscriptions/install/templates/app/controllers/concerns/create_subscription.rb +17 -0
- data/lib/generators/solidus_subscriptions/install/templates/app/views/cart_line_items/_subscription_fields.html.erb +30 -0
- data/lib/generators/solidus_subscriptions/install/templates/initializer.rb +3 -1
- data/lib/solidus_subscriptions/configuration.rb +29 -6
- data/lib/solidus_subscriptions/dispatcher/payment_failed_dispatcher.rb +2 -2
- data/lib/solidus_subscriptions/dispatcher/success_dispatcher.rb +2 -2
- data/lib/solidus_subscriptions/engine.rb +28 -0
- data/lib/solidus_subscriptions/permission_sets/default_customer.rb +1 -1
- data/lib/solidus_subscriptions/processing_error_handlers/rails_logger.rb +25 -0
- data/lib/solidus_subscriptions/subscription_generator.rb +6 -0
- data/lib/solidus_subscriptions/version.rb +1 -1
- data/solidus_subscriptions.gemspec +6 -6
- data/spec/controllers/spree/api/line_items_controller_spec.rb +63 -28
- data/spec/controllers/spree/api/users_controller_spec.rb +3 -0
- data/spec/decorators/controllers/solidus_subscriptions/spree/orders_controller/create_subscription_line_items_spec.rb +4 -4
- data/spec/decorators/models/solidus_subscriptions/spree/variant/auto_delete_from_subscriptions_spec.rb +2 -2
- data/spec/features/admin/subscriptions_spec.rb +13 -3
- data/spec/jobs/solidus_subscriptions/create_subscription_job_spec.rb +20 -0
- data/spec/jobs/solidus_subscriptions/process_installment_job_spec.rb +17 -0
- data/spec/lib/solidus_subscriptions/dispatcher/payment_failed_dispatcher_spec.rb +3 -3
- data/spec/lib/solidus_subscriptions/dispatcher/success_dispatcher_spec.rb +3 -3
- data/spec/lib/solidus_subscriptions/subscription_generator_spec.rb +1 -1
- data/spec/models/solidus_subscriptions/installment_spec.rb +1 -1
- data/spec/models/solidus_subscriptions/subscription_spec.rb +893 -16
- data/spec/models/spree/wallet_payment_source_spec.rb +3 -3
- data/spec/requests/api/v1/subscriptions_spec.rb +229 -0
- data/spec/subscribers/solidus_subscriptions/churn_buster_subscriber_spec.rb +8 -8
- data/spec/subscribers/solidus_subscriptions/order_subscriber_spec.rb +13 -0
- metadata +24 -17
- data/app/decorators/models/solidus_subscriptions/spree/order/finalize_creates_subscriptions.rb +0 -25
- data/config/initializers/subscribers.rb +0 -9
- data/spec/decorators/models/solidus_subscriptions/spree/order/finalize_creates_subscriptions_spec.rb +0 -32
- /data/{app → lib}/views/spree/frontend/products/_subscription_line_item_fields.html.erb +0 -0
| @@ -27,6 +27,20 @@ module SolidusSubscriptions | |
| 27 27 | 
             
                      def handle_subscription_line_items
         | 
| 28 28 | 
             
                        create_subscription_line_item(@line_item)
         | 
| 29 29 | 
             
                      end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                      def line_items_attributes
         | 
| 32 | 
            +
                        super.tap do |attrs|
         | 
| 33 | 
            +
                          if params[:subscription_line_items_attributes]
         | 
| 34 | 
            +
                            attrs[:line_items_attributes].merge!(
         | 
| 35 | 
            +
                              subscription_line_items_attributes: subscription_line_item_params
         | 
| 36 | 
            +
                            )
         | 
| 37 | 
            +
                          end
         | 
| 38 | 
            +
                        end
         | 
| 39 | 
            +
                      end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                      def subscription_line_item_params
         | 
| 42 | 
            +
                        params[:subscription_line_items_attributes].permit(SolidusSubscriptions::PermittedAttributes.subscription_line_item_attributes)
         | 
| 43 | 
            +
                      end
         | 
| 30 44 | 
             
                    end
         | 
| 31 45 | 
             
                  end
         | 
| 32 46 | 
             
                end
         | 
| @@ -6,6 +6,7 @@ module SolidusSubscriptions | |
| 6 6 | 
             
                  source_root File.expand_path('templates', __dir__)
         | 
| 7 7 |  | 
| 8 8 | 
             
                  class_option :auto_run_migrations, type: :boolean, default: false
         | 
| 9 | 
            +
                  class_option :frontend, type: :string, default: 'classic'
         | 
| 9 10 |  | 
| 10 11 | 
             
                  def copy_initializer
         | 
| 11 12 | 
             
                    template 'initializer.rb', 'config/initializers/solidus_subscriptions.rb'
         | 
| @@ -15,6 +16,21 @@ module SolidusSubscriptions | |
| 15 16 | 
             
                    append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/solidus_subscriptions\n"
         | 
| 16 17 | 
             
                  end
         | 
| 17 18 |  | 
| 19 | 
            +
                  def copy_starter_frontend_files
         | 
| 20 | 
            +
                    return if options[:frontend] != 'starter'
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    copy_file 'app/views/cart_line_items/_subscription_fields.html.erb'
         | 
| 23 | 
            +
                    prepend_to_file 'app/views/cart_line_items/_product_submit.html.erb', "<%= render 'cart_line_items/subscription_fields' %>\n"
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    copy_file 'app/controllers/concerns/create_subscription.rb'
         | 
| 26 | 
            +
                    insert_into_file 'app/controllers/cart_line_items_controller.rb', after: "class CartLineItemsController < StoreController\n" do
         | 
| 27 | 
            +
                      <<~RUBY.indent(2)
         | 
| 28 | 
            +
                        include CreateSubscription
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                      RUBY
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 18 34 | 
             
                  def add_migrations
         | 
| 19 35 | 
             
                    run 'bin/rails railties:install:migrations FROM=solidus_subscriptions'
         | 
| 20 36 | 
             
                  end
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module CreateSubscription
         | 
| 4 | 
            +
              extend ActiveSupport::Concern
         | 
| 5 | 
            +
              include SolidusSubscriptions::SubscriptionLineItemBuilder
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              included do
         | 
| 8 | 
            +
                after_action :handle_subscription_line_items, only: :create, if: ->{ params[:subscription_line_item] }
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              private
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              def handle_subscription_line_items
         | 
| 14 | 
            +
                line_item = @current_order.line_items.find_by(variant_id: params[:variant_id])
         | 
| 15 | 
            +
                create_subscription_line_item(line_item)
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            <%= content_tag :h3, t('.subscription_fields') %>
         | 
| 2 | 
            +
            <%= fields_for :'subscription_line_item', SolidusSubscriptions::LineItem.new do |ff| %>
         | 
| 3 | 
            +
              <div>
         | 
| 4 | 
            +
                <%= ff.label :quantity, t('.quantity') %>
         | 
| 5 | 
            +
                <%= ff.number_field :quantity %>
         | 
| 6 | 
            +
                <%= ff.label :quantity, t('.quantity_suffix') %>
         | 
| 7 | 
            +
              </div>
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              <div>
         | 
| 10 | 
            +
                <%= ff.label :interval_length, t('.interval_length') %>
         | 
| 11 | 
            +
                <%= ff.number_field :interval_length %>
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                <%= ff.collection_radio_buttons :interval_units, SolidusSubscriptions::LineItem.interval_units.to_a, :first, :first %>
         | 
| 14 | 
            +
              </div>
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              <%= ff.hidden_field :subscribable_id %>
         | 
| 17 | 
            +
            <% end %>
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            <script>
         | 
| 20 | 
            +
              document.addEventListener("DOMContentLoaded", function(e) {
         | 
| 21 | 
            +
                var cartForm = document.querySelector('.product-page__info form');
         | 
| 22 | 
            +
                cartForm.addEventListener('submit', function(e) {
         | 
| 23 | 
            +
                  var quantityInput = e.target.querySelector('[name*="quantity"]');
         | 
| 24 | 
            +
                  var subscriptionQuantityInput = e.target.querySelector('[name*="subscribable_id"]');
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  subscriptionQuantityInput.value = quantityInput.value;
         | 
| 27 | 
            +
                  return true;
         | 
| 28 | 
            +
                });
         | 
| 29 | 
            +
              });
         | 
| 30 | 
            +
            </script>
         | 
| @@ -31,7 +31,9 @@ SolidusSubscriptions.configure do |config| | |
| 31 31 | 
             
              # on an error tracking system.
         | 
| 32 32 | 
             
              # Though not recommended due to the retry mechanisms built into this gem, the error can be
         | 
| 33 33 | 
             
              # re-raised if the default retry behaviour is required in ActiveJob.
         | 
| 34 | 
            -
              # | 
| 34 | 
            +
              #
         | 
| 35 | 
            +
              # By default, it only logs the error message using Rails.logger.error.
         | 
| 36 | 
            +
              # config.processing_error_handler = SolidusSubscriptions::ProcessingErrorHandlers::RailsLogger
         | 
| 35 37 |  | 
| 36 38 | 
             
              # ========================================= Dispatchers ==========================================
         | 
| 37 39 | 
             
              #
         | 
| @@ -3,17 +3,35 @@ | |
| 3 3 | 
             
            module SolidusSubscriptions
         | 
| 4 4 | 
             
              class Configuration
         | 
| 5 5 | 
             
                attr_accessor(
         | 
| 6 | 
            -
                  : | 
| 7 | 
            -
                  :churn_buster_api_key, | 
| 6 | 
            +
                  :churn_buster_account_id,
         | 
| 7 | 
            +
                  :churn_buster_api_key,
         | 
| 8 | 
            +
                  :clear_past_installments,
         | 
| 9 | 
            +
                  :maximum_reprocessing_time,
         | 
| 10 | 
            +
                  :maximum_total_skips,
         | 
| 8 11 | 
             
                )
         | 
| 9 12 |  | 
| 10 13 | 
             
                attr_writer(
         | 
| 11 | 
            -
                  : | 
| 12 | 
            -
                  : | 
| 13 | 
            -
                  :minimum_cancellation_notice, | 
| 14 | 
            -
                  : | 
| 14 | 
            +
                  :failure_dispatcher_class,
         | 
| 15 | 
            +
                  :maximum_successive_skips,
         | 
| 16 | 
            +
                  :minimum_cancellation_notice,
         | 
| 17 | 
            +
                  :order_creator_class,
         | 
| 18 | 
            +
                  :out_of_stock_dispatcher,
         | 
| 19 | 
            +
                  :payment_failed_dispatcher_class,
         | 
| 20 | 
            +
                  :processing_error_handler,
         | 
| 21 | 
            +
                  :processing_queue,
         | 
| 22 | 
            +
                  :reprocessing_interval,
         | 
| 23 | 
            +
                  :subscribable_class,
         | 
| 24 | 
            +
                  :subscription_attributes,
         | 
| 25 | 
            +
                  :subscription_generator_class,
         | 
| 26 | 
            +
                  :subscription_line_item_attributes,
         | 
| 27 | 
            +
                  :success_dispatcher_class,
         | 
| 15 28 | 
             
                )
         | 
| 16 29 |  | 
| 30 | 
            +
                def subscription_generator_class
         | 
| 31 | 
            +
                  @subscription_generator_class ||= 'SolidusSubscriptions::SubscriptionGenerator'
         | 
| 32 | 
            +
                  @subscription_generator_class.constantize
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 17 35 | 
             
                def success_dispatcher_class
         | 
| 18 36 | 
             
                  @success_dispatcher_class ||= 'SolidusSubscriptions::Dispatcher::SuccessDispatcher'
         | 
| 19 37 | 
             
                  @success_dispatcher_class.constantize
         | 
| @@ -34,6 +52,11 @@ module SolidusSubscriptions | |
| 34 52 | 
             
                  @out_of_stock_dispatcher_class.constantize
         | 
| 35 53 | 
             
                end
         | 
| 36 54 |  | 
| 55 | 
            +
                def processing_error_handler
         | 
| 56 | 
            +
                  @processing_error_handler ||= 'SolidusSubscriptions::ProcessingErrorHandlers::RailsLogger'
         | 
| 57 | 
            +
                  @processing_error_handler.constantize
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 37 60 | 
             
                def maximum_successive_skips
         | 
| 38 61 | 
             
                  @maximum_successive_skips ||= 1
         | 
| 39 62 | 
             
                end
         | 
| @@ -8,8 +8,8 @@ module SolidusSubscriptions | |
| 8 8 | 
             
                    order.cancel
         | 
| 9 9 | 
             
                    installment.payment_failed!(order)
         | 
| 10 10 |  | 
| 11 | 
            -
                    :: | 
| 12 | 
            -
                      'solidus_subscriptions.installment_failed_payment',
         | 
| 11 | 
            +
                    ::SolidusSupport::LegacyEventCompat::Bus.publish(
         | 
| 12 | 
            +
                      :'solidus_subscriptions.installment_failed_payment',
         | 
| 13 13 | 
             
                      installment: installment,
         | 
| 14 14 | 
             
                      order: order,
         | 
| 15 15 | 
             
                    )
         | 
| @@ -6,8 +6,8 @@ module SolidusSubscriptions | |
| 6 6 | 
             
                  def dispatch
         | 
| 7 7 | 
             
                    installment.success!(order)
         | 
| 8 8 |  | 
| 9 | 
            -
                    :: | 
| 10 | 
            -
                      'solidus_subscriptions.installment_succeeded',
         | 
| 9 | 
            +
                    ::SolidusSupport::LegacyEventCompat::Bus.publish(
         | 
| 10 | 
            +
                      :'solidus_subscriptions.installment_succeeded',
         | 
| 11 11 | 
             
                      installment: installment,
         | 
| 12 12 | 
             
                      order: order,
         | 
| 13 13 | 
             
                    )
         | 
| @@ -6,6 +6,7 @@ require 'solidus_subscriptions' | |
| 6 6 | 
             
            require 'solidus_subscriptions/permitted_attributes'
         | 
| 7 7 | 
             
            require 'solidus_subscriptions/configuration'
         | 
| 8 8 | 
             
            require 'solidus_subscriptions/processor'
         | 
| 9 | 
            +
            require 'solidus_subscriptions/processing_error_handlers/rails_logger'
         | 
| 9 10 |  | 
| 10 11 | 
             
            module SolidusSubscriptions
         | 
| 11 12 | 
             
              class Engine < Rails::Engine
         | 
| @@ -48,6 +49,33 @@ module SolidusSubscriptions | |
| 48 49 | 
             
                    )
         | 
| 49 50 | 
             
                  end
         | 
| 50 51 | 
             
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                initializer 'solidus_subscriptions.pub_sub' do |app|
         | 
| 54 | 
            +
                  unless SolidusSupport::LegacyEventCompat.using_legacy?
         | 
| 55 | 
            +
                    app.reloader.to_prepare do
         | 
| 56 | 
            +
                      %i[
         | 
| 57 | 
            +
                        subscription_created
         | 
| 58 | 
            +
                        subscription_activated
         | 
| 59 | 
            +
                        subscription_canceled
         | 
| 60 | 
            +
                        subscription_ended
         | 
| 61 | 
            +
                        subscription_skipped
         | 
| 62 | 
            +
                        subscription_resumed
         | 
| 63 | 
            +
                        subscription_paused
         | 
| 64 | 
            +
                        subscription_frequency_changed
         | 
| 65 | 
            +
                        subscription_shipping_address_changed
         | 
| 66 | 
            +
                        subscription_billing_address_changed
         | 
| 67 | 
            +
                        installment_succeeded
         | 
| 68 | 
            +
                        installment_failed_payment
         | 
| 69 | 
            +
                        subscription_payment_method_changed
         | 
| 70 | 
            +
                      ].each do |event_name|
         | 
| 71 | 
            +
                        ::Spree::Bus.register(:"solidus_subscriptions.#{event_name}")
         | 
| 72 | 
            +
                      end
         | 
| 73 | 
            +
                      SolidusSubscriptions::ChurnBusterSubscriber.omnes_subscriber.subscribe_to(::Spree::Bus)
         | 
| 74 | 
            +
                      SolidusSubscriptions::EventStorageSubscriber.omnes_subscriber.subscribe_to(::Spree::Bus)
         | 
| 75 | 
            +
                      SolidusSubscriptions::OrderSubscriber.omnes_subscriber.subscribe_to(::Spree::Bus)
         | 
| 76 | 
            +
                    end
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                end
         | 
| 51 79 | 
             
              end
         | 
| 52 80 |  | 
| 53 81 | 
             
              def self.table_name_prefix
         | 
| @@ -4,7 +4,7 @@ module SolidusSubscriptions | |
| 4 4 | 
             
              module PermissionSets
         | 
| 5 5 | 
             
                class DefaultCustomer < ::Spree::PermissionSets::Base
         | 
| 6 6 | 
             
                  def activate!
         | 
| 7 | 
            -
                    can [:show, :display, :update, :skip, :cancel], Subscription, ['user_id = ?', user.id] do |subscription, guest_token|
         | 
| 7 | 
            +
                    can [:show, :display, :update, :skip, :cancel, :pause, :resume], Subscription, ['user_id = ?', user.id] do |subscription, guest_token|
         | 
| 8 8 | 
             
                      (subscription.guest_token.present? && subscription.guest_token == guest_token) ||
         | 
| 9 9 | 
             
                        (subscription.user && subscription.user == user)
         | 
| 10 10 | 
             
                    end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module SolidusSubscriptions
         | 
| 4 | 
            +
              module ProcessingErrorHandlers
         | 
| 5 | 
            +
                class RailsLogger
         | 
| 6 | 
            +
                  def self.call(exception, installment = nil)
         | 
| 7 | 
            +
                    new(exception, installment).call
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def initialize(exception, installment = nil)
         | 
| 11 | 
            +
                    @exception = exception
         | 
| 12 | 
            +
                    @installment = installment
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def call
         | 
| 16 | 
            +
                    Rails.logger.error("Error processing installment with ID=#{installment.id}:") if installment
         | 
| 17 | 
            +
                    Rails.logger.error(exception.message)
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  private
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  attr_reader :exception, :installment
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| @@ -8,6 +8,12 @@ module SolidusSubscriptions | |
| 8 8 |  | 
| 9 9 | 
             
                SubscriptionConfiguration = Struct.new(:interval_length, :interval_units, :end_date)
         | 
| 10 10 |  | 
| 11 | 
            +
                def call(order)
         | 
| 12 | 
            +
                  group(order.subscription_line_items).each { |line_items| activate(line_items) }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  order.reload
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 11 17 | 
             
                # Create and persist a subscription for a collection of subscription
         | 
| 12 18 | 
             
                #   line items
         | 
| 13 19 | 
             
                #
         | 
| @@ -10,14 +10,14 @@ Gem::Specification.new do |spec| | |
| 10 10 |  | 
| 11 11 | 
             
              spec.summary = 'Add subscription support to Solidus'
         | 
| 12 12 | 
             
              spec.description = 'Add subscription support to Solidus'
         | 
| 13 | 
            -
              spec.homepage = 'https://github.com/solidusio | 
| 13 | 
            +
              spec.homepage = 'https://github.com/solidusio/solidus_subscriptions'
         | 
| 14 14 | 
             
              spec.license = 'BSD-3-Clause'
         | 
| 15 15 |  | 
| 16 16 | 
             
              spec.metadata['homepage_uri'] = spec.homepage
         | 
| 17 | 
            -
              spec.metadata['source_code_uri'] = 'https://github.com/solidusio | 
| 18 | 
            -
              spec.metadata['changelog_uri'] = 'https://github.com/solidusio | 
| 17 | 
            +
              spec.metadata['source_code_uri'] = 'https://github.com/solidusio/solidus_subscriptions'
         | 
| 18 | 
            +
              spec.metadata['changelog_uri'] = 'https://github.com/solidusio/solidus_subscriptions/blob/master/CHANGELOG.md'
         | 
| 19 19 |  | 
| 20 | 
            -
              spec.required_ruby_version = Gem::Requirement.new(' | 
| 20 | 
            +
              spec.required_ruby_version = Gem::Requirement.new('>= 2.5')
         | 
| 21 21 |  | 
| 22 22 | 
             
              # Specify which files should be added to the gem when it is released.
         | 
| 23 23 | 
             
              # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
         | 
| @@ -32,8 +32,8 @@ Gem::Specification.new do |spec| | |
| 32 32 | 
             
              spec.add_dependency 'deface'
         | 
| 33 33 | 
             
              spec.add_dependency 'httparty', '~> 0.18'
         | 
| 34 34 | 
             
              spec.add_dependency 'i18n'
         | 
| 35 | 
            -
              spec.add_dependency 'solidus_core', '>= 2. | 
| 36 | 
            -
              spec.add_dependency 'solidus_support', '~> 0. | 
| 35 | 
            +
              spec.add_dependency 'solidus_core', '>= 2.11', '< 4'
         | 
| 36 | 
            +
              spec.add_dependency 'solidus_support', '~> 0.9'
         | 
| 37 37 | 
             
              spec.add_dependency 'state_machines'
         | 
| 38 38 |  | 
| 39 39 | 
             
              spec.add_development_dependency 'rspec-activemodel-mocks'
         | 
| @@ -31,7 +31,7 @@ RSpec.describe Spree::Api::LineItemsController, type: :controller do | |
| 31 31 |  | 
| 32 32 | 
             
                  it 'creates a line item' do
         | 
| 33 33 | 
             
                    expect { post_create }.
         | 
| 34 | 
            -
                      to change | 
| 34 | 
            +
                      to change(Spree::LineItem, :count).
         | 
| 35 35 | 
             
                      from(0).to(1)
         | 
| 36 36 | 
             
                  end
         | 
| 37 37 | 
             
                end
         | 
| @@ -54,7 +54,7 @@ RSpec.describe Spree::Api::LineItemsController, type: :controller do | |
| 54 54 |  | 
| 55 55 | 
             
                  it 'creates a new subscription line item' do
         | 
| 56 56 | 
             
                    expect { post_create }.
         | 
| 57 | 
            -
                      to change | 
| 57 | 
            +
                      to change(SolidusSubscriptions::LineItem, :count).
         | 
| 58 58 | 
             
                      from(0).to(1)
         | 
| 59 59 | 
             
                  end
         | 
| 60 60 | 
             
                end
         | 
| @@ -65,39 +65,74 @@ RSpec.describe Spree::Api::LineItemsController, type: :controller do | |
| 65 65 | 
             
              end
         | 
| 66 66 |  | 
| 67 67 | 
             
              describe 'patch :update' do
         | 
| 68 | 
            -
                subject(: | 
| 68 | 
            +
                subject(:patch_update) { patch :update, params: params }
         | 
| 69 69 |  | 
| 70 70 | 
             
                let(:params) { line_item_params }
         | 
| 71 | 
            -
                let!(:variant) { create :variant }
         | 
| 72 | 
            -
                let!(:order) { create :order }
         | 
| 73 | 
            -
                let!(:line_item) { create :line_item, order: order, variant: variant }
         | 
| 74 71 |  | 
| 75 | 
            -
                 | 
| 76 | 
            -
                  {
         | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
                     | 
| 81 | 
            -
             | 
| 82 | 
            -
                       | 
| 83 | 
            -
                       | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
                       | 
| 89 | 
            -
                       | 
| 90 | 
            -
             | 
| 72 | 
            +
                context 'when adding subscription information' do
         | 
| 73 | 
            +
                  let(:variant) { create :variant }
         | 
| 74 | 
            +
                  let(:order) { create :order }
         | 
| 75 | 
            +
                  let(:line_item) { create :line_item, order: order, variant: variant }
         | 
| 76 | 
            +
                  let(:line_item_params) do
         | 
| 77 | 
            +
                    {
         | 
| 78 | 
            +
                      id: line_item.id,
         | 
| 79 | 
            +
                      order_id: order.number,
         | 
| 80 | 
            +
                      order_token: order.guest_token,
         | 
| 81 | 
            +
                      format: 'json',
         | 
| 82 | 
            +
                      line_item: {
         | 
| 83 | 
            +
                        quantity: 1,
         | 
| 84 | 
            +
                        variant_id: variant.id
         | 
| 85 | 
            +
                      },
         | 
| 86 | 
            +
                      subscription_line_item: {
         | 
| 87 | 
            +
                        quantity: 2,
         | 
| 88 | 
            +
                        end_date: '1990/10/12',
         | 
| 89 | 
            +
                        subscribable_id: variant.id,
         | 
| 90 | 
            +
                        interval_length: 30,
         | 
| 91 | 
            +
                        interval_units: "day"
         | 
| 92 | 
            +
                      }
         | 
| 91 93 | 
             
                    }
         | 
| 92 | 
            -
                   | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                  it { is_expected.to be_successful }
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  it 'creates a new subscription line item' do
         | 
| 99 | 
            +
                    expect { patch_update }.
         | 
| 100 | 
            +
                      to change(SolidusSubscriptions::LineItem, :count).
         | 
| 101 | 
            +
                      from(0).to(1)
         | 
| 102 | 
            +
                  end
         | 
| 93 103 | 
             
                end
         | 
| 94 104 |  | 
| 95 | 
            -
                 | 
| 105 | 
            +
                context 'when updating subscription information' do
         | 
| 106 | 
            +
                  let!(:line_item) { create :subscription_line_item, interval_length: 30 }
         | 
| 107 | 
            +
                  let(:variant) { line_item.spree_line_item.variant }
         | 
| 108 | 
            +
                  let(:order) { line_item.spree_line_item.order }
         | 
| 109 | 
            +
                  let(:line_item_params) do
         | 
| 110 | 
            +
                    {
         | 
| 111 | 
            +
                      id: line_item.spree_line_item.id,
         | 
| 112 | 
            +
                      order_id: order.number,
         | 
| 113 | 
            +
                      order_token: order.guest_token,
         | 
| 114 | 
            +
                      format: 'json',
         | 
| 115 | 
            +
                      line_item: {
         | 
| 116 | 
            +
                        quantity: 1,
         | 
| 117 | 
            +
                      },
         | 
| 118 | 
            +
                      subscription_line_items_attributes: {
         | 
| 119 | 
            +
                        id: line_item.id,
         | 
| 120 | 
            +
                        interval_length: 15,
         | 
| 121 | 
            +
                      }
         | 
| 122 | 
            +
                    }
         | 
| 123 | 
            +
                  end
         | 
| 96 124 |  | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
                     | 
| 125 | 
            +
                  it { is_expected.to be_successful }
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                  it 'does not create a new subscription line item' do
         | 
| 128 | 
            +
                    expect { patch_update }.
         | 
| 129 | 
            +
                      not_to change(SolidusSubscriptions::LineItem, :count)
         | 
| 130 | 
            +
                  end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                  it 'updates a new subscription line item' do
         | 
| 133 | 
            +
                    expect { patch_update }.
         | 
| 134 | 
            +
                      to change { line_item.reload.interval_length }.from(30).to(15)
         | 
| 135 | 
            +
                  end
         | 
| 101 136 | 
             
                end
         | 
| 102 137 | 
             
              end
         | 
| 103 138 | 
             
            end
         | 
| @@ -39,6 +39,9 @@ RSpec.describe Spree::Api::UsersController, type: :controller do | |
| 39 39 | 
             
                end
         | 
| 40 40 |  | 
| 41 41 | 
             
                it 'updates the subscription line items' do
         | 
| 42 | 
            +
                  allow(::Spree::Deprecation).to receive(:warn).with(a_string_matching(
         | 
| 43 | 
            +
                    'Creating or updating subscriptions through Spree::User nested attributes is deprecated'
         | 
| 44 | 
            +
                  ))
         | 
| 42 45 | 
             
                  update_user
         | 
| 43 46 | 
             
                  line_item = subscription.line_items.reload.first
         | 
| 44 47 |  | 
| @@ -9,7 +9,7 @@ RSpec.describe SolidusSubscriptions::Spree::OrdersController::CreateSubscription | |
| 9 9 | 
             
              let!(:user) { create :user }
         | 
| 10 10 |  | 
| 11 11 | 
             
              before do
         | 
| 12 | 
            -
                allow(controller).to receive_messages( | 
| 12 | 
            +
                allow(controller).to receive_messages(spree_current_user: user)
         | 
| 13 13 | 
             
                create :store
         | 
| 14 14 | 
             
              end
         | 
| 15 15 |  | 
| @@ -30,13 +30,13 @@ RSpec.describe SolidusSubscriptions::Spree::OrdersController::CreateSubscription | |
| 30 30 |  | 
| 31 31 | 
             
                  it 'creates an order' do
         | 
| 32 32 | 
             
                    expect { populate }.
         | 
| 33 | 
            -
                      to change | 
| 33 | 
            +
                      to change(Spree::Order, :count).
         | 
| 34 34 | 
             
                      from(0).to(1)
         | 
| 35 35 | 
             
                  end
         | 
| 36 36 |  | 
| 37 37 | 
             
                  it 'creates a line item' do
         | 
| 38 38 | 
             
                    expect { populate }.
         | 
| 39 | 
            -
                      to change | 
| 39 | 
            +
                      to change(Spree::LineItem, :count).
         | 
| 40 40 | 
             
                      from(0).to(1)
         | 
| 41 41 | 
             
                  end
         | 
| 42 42 | 
             
                end
         | 
| @@ -59,7 +59,7 @@ RSpec.describe SolidusSubscriptions::Spree::OrdersController::CreateSubscription | |
| 59 59 |  | 
| 60 60 | 
             
                  it 'creates a new subscription line item' do
         | 
| 61 61 | 
             
                    expect { populate }.
         | 
| 62 | 
            -
                      to change | 
| 62 | 
            +
                      to change(SolidusSubscriptions::LineItem, :count).
         | 
| 63 63 | 
             
                      from(0).to(1)
         | 
| 64 64 | 
             
                  end
         | 
| 65 65 |  | 
| @@ -10,7 +10,7 @@ RSpec.describe SolidusSubscriptions::Spree::Variant::AutoDeleteFromSubscriptions | |
| 10 10 | 
             
                  subscription = create(:subscription)
         | 
| 11 11 | 
             
                  create(:subscription_line_item, subscription: subscription, subscribable: subject)
         | 
| 12 12 |  | 
| 13 | 
            -
                  expect { subject.discard }.to change | 
| 13 | 
            +
                  expect { subject.discard }.to change(SolidusSubscriptions::LineItem, :count).by(-1)
         | 
| 14 14 | 
             
                end
         | 
| 15 15 | 
             
              end
         | 
| 16 16 |  | 
| @@ -19,7 +19,7 @@ RSpec.describe SolidusSubscriptions::Spree::Variant::AutoDeleteFromSubscriptions | |
| 19 19 | 
             
                  subscription = create(:subscription)
         | 
| 20 20 | 
             
                  create(:subscription_line_item, subscription: subscription, subscribable: subject)
         | 
| 21 21 |  | 
| 22 | 
            -
                  expect { subject.destroy }.to change | 
| 22 | 
            +
                  expect { subject.destroy }.to change(SolidusSubscriptions::LineItem, :count).by(-1)
         | 
| 23 23 | 
             
                end
         | 
| 24 24 | 
             
              end
         | 
| 25 25 | 
             
            end
         | 
| @@ -25,7 +25,7 @@ RSpec.describe 'Subscriptions admin' do | |
| 25 25 | 
             
                expect(subscription.billing_address.zipcode).to eq('33167')
         | 
| 26 26 | 
             
              end
         | 
| 27 27 |  | 
| 28 | 
            -
              it 'Creates a subscription' do
         | 
| 28 | 
            +
              it 'Creates a subscription' do # rubocop:disable RSpec/MultipleExpectations
         | 
| 29 29 | 
             
                variant = create(:variant, subscribable: true)
         | 
| 30 30 | 
             
                create(:user)
         | 
| 31 31 | 
             
                create(:store)
         | 
| @@ -53,10 +53,20 @@ RSpec.describe 'Subscriptions admin' do | |
| 53 53 | 
             
                  end
         | 
| 54 54 | 
             
                end
         | 
| 55 55 |  | 
| 56 | 
            -
                select variant. | 
| 56 | 
            +
                select variant.pretty_name, from: 'Subscribable'
         | 
| 57 57 | 
             
                fill_in 'Quantity', with: 1
         | 
| 58 58 |  | 
| 59 | 
            -
                expect | 
| 59 | 
            +
                expect(SolidusSubscriptions::Subscription.count).to eq(0)
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                # The State field is controlled by JS, so we need to set it at the last moment
         | 
| 62 | 
            +
                # available.
         | 
| 63 | 
            +
                state_id = Spree::State.last.id.to_s
         | 
| 64 | 
            +
                find('input#subscription_shipping_address_attributes_state_id', visible: :all).set(state_id)
         | 
| 65 | 
            +
                find('input#subscription_billing_address_attributes_state_id', visible: :all).set(state_id)
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                click_on 'Create'
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                expect(SolidusSubscriptions::Subscription.count).to eq(1)
         | 
| 60 70 |  | 
| 61 71 | 
             
                expect(page).to have_text('Subscription has been successfully created!')
         | 
| 62 72 | 
             
              end
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe SolidusSubscriptions::CreateSubscriptionJob do
         | 
| 4 | 
            +
              describe '#perform' do
         | 
| 5 | 
            +
                it 'creates new subscriptions for an order' do
         | 
| 6 | 
            +
                  order = create(:order, :with_subscription_line_items)
         | 
| 7 | 
            +
                  subscription_line_item = order.subscription_line_items.last
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  described_class.perform_now(order)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  expect(SolidusSubscriptions::Subscription.count).to eq(order.subscription_line_items.count)
         | 
| 12 | 
            +
                  subscription = SolidusSubscriptions::Subscription.last
         | 
| 13 | 
            +
                  expect(subscription).to have_attributes(
         | 
| 14 | 
            +
                    user_id: order.user_id,
         | 
| 15 | 
            +
                    actionable_date: Time.zone.today + subscription.interval,
         | 
| 16 | 
            +
                    line_items: [subscription_line_item]
         | 
| 17 | 
            +
                  )
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| @@ -12,7 +12,24 @@ RSpec.describe SolidusSubscriptions::ProcessInstallmentJob do | |
| 12 12 | 
             
              end
         | 
| 13 13 |  | 
| 14 14 | 
             
              context 'when handling #perform errors' do
         | 
| 15 | 
            +
                it 'by default logs exception data without raising exceptions' do # rubocop:disable RSpec/MultipleExpectations
         | 
| 16 | 
            +
                  installment = build_stubbed(:installment)
         | 
| 17 | 
            +
                  checkout = instance_double(SolidusSubscriptions::Checkout).tap do |c|
         | 
| 18 | 
            +
                    allow(c).to receive(:process).and_raise('test error')
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                  allow(SolidusSubscriptions::Checkout).to receive(:new).and_return(checkout)
         | 
| 21 | 
            +
                  allow(Rails.logger).to receive(:error)
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  expect {
         | 
| 24 | 
            +
                    described_class.perform_now(installment)
         | 
| 25 | 
            +
                  }.not_to raise_error
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  expect(Rails.logger).to have_received(:error).with("Error processing installment with ID=#{installment.id}:").ordered
         | 
| 28 | 
            +
                  expect(Rails.logger).to have_received(:error).with("test error").ordered
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 15 31 | 
             
                it 'swallows error when a proc is not configured' do
         | 
| 32 | 
            +
                  stub_config(processing_error_handler: nil )
         | 
| 16 33 | 
             
                  checkout = instance_double(SolidusSubscriptions::Checkout).tap do |c|
         | 
| 17 34 | 
             
                    allow(c).to receive(:process).and_raise('test error')
         | 
| 18 35 | 
             
                  end
         | 
| @@ -27,15 +27,15 @@ RSpec.describe SolidusSubscriptions::Dispatcher::PaymentFailedDispatcher do | |
| 27 27 | 
             
                end
         | 
| 28 28 |  | 
| 29 29 | 
             
                it 'fires an installments_failed_payment event' do
         | 
| 30 | 
            -
                  stub_const(' | 
| 30 | 
            +
                  stub_const('SolidusSupport::LegacyEventCompat::Bus', class_spy(SolidusSupport::LegacyEventCompat::Bus))
         | 
| 31 31 | 
             
                  installment = instance_spy(SolidusSubscriptions::Installment)
         | 
| 32 32 | 
             
                  order = create(:order_with_line_items)
         | 
| 33 33 |  | 
| 34 34 | 
             
                  dispatcher = described_class.new(installment, order)
         | 
| 35 35 | 
             
                  dispatcher.dispatch
         | 
| 36 36 |  | 
| 37 | 
            -
                  expect( | 
| 38 | 
            -
                    'solidus_subscriptions.installment_failed_payment',
         | 
| 37 | 
            +
                  expect(SolidusSupport::LegacyEventCompat::Bus).to have_received(:publish).with(
         | 
| 38 | 
            +
                    :'solidus_subscriptions.installment_failed_payment',
         | 
| 39 39 | 
             
                    installment: installment,
         | 
| 40 40 | 
             
                    order: order,
         | 
| 41 41 | 
             
                  )
         | 
| @@ -13,15 +13,15 @@ RSpec.describe SolidusSubscriptions::Dispatcher::SuccessDispatcher do | |
| 13 13 | 
             
                end
         | 
| 14 14 |  | 
| 15 15 | 
             
                it 'fires an installments_succeeded event' do
         | 
| 16 | 
            -
                  stub_const(' | 
| 16 | 
            +
                  stub_const('SolidusSupport::LegacyEventCompat::Bus', class_spy(SolidusSupport::LegacyEventCompat::Bus))
         | 
| 17 17 | 
             
                  installment = instance_spy(SolidusSubscriptions::Installment)
         | 
| 18 18 | 
             
                  order = create(:order_with_line_items)
         | 
| 19 19 |  | 
| 20 20 | 
             
                  dispatcher = described_class.new(installment, order)
         | 
| 21 21 | 
             
                  dispatcher.dispatch
         | 
| 22 22 |  | 
| 23 | 
            -
                  expect( | 
| 24 | 
            -
                    'solidus_subscriptions.installment_succeeded',
         | 
| 23 | 
            +
                  expect(SolidusSupport::LegacyEventCompat::Bus).to have_received(:publish).with(
         | 
| 24 | 
            +
                    :'solidus_subscriptions.installment_succeeded',
         | 
| 25 25 | 
             
                    installment: installment,
         | 
| 26 26 | 
             
                    order: order,
         | 
| 27 27 | 
             
                  )
         | 
| @@ -75,7 +75,7 @@ RSpec.describe SolidusSubscriptions::SubscriptionGenerator do | |
| 75 75 | 
             
                    weekly_subscriptions,
         | 
| 76 76 | 
             
                    expiring_subscriptions,
         | 
| 77 77 | 
             
                  ]
         | 
| 78 | 
            -
                  grouping_result = described_class.group(subscriptions. | 
| 78 | 
            +
                  grouping_result = described_class.group(subscriptions.flatten)
         | 
| 79 79 |  | 
| 80 80 | 
             
                  expect(grouping_result).to match_array(subscriptions)
         | 
| 81 81 | 
             
                end
         | 
| @@ -46,7 +46,7 @@ RSpec.describe SolidusSubscriptions::Installment, type: :model do | |
| 46 46 |  | 
| 47 47 | 
             
                it 'creates a new installment detail' do
         | 
| 48 48 | 
             
                  expect { success }.
         | 
| 49 | 
            -
                    to change | 
| 49 | 
            +
                    to change(SolidusSubscriptions::InstallmentDetail, :count).
         | 
| 50 50 | 
             
                    by(1)
         | 
| 51 51 | 
             
                end
         | 
| 52 52 |  |