summaryrefslogtreecommitdiff
path: root/lib/solidus_subscriptions
diff options
context:
space:
mode:
Diffstat (limited to 'lib/solidus_subscriptions')
-rw-r--r--lib/solidus_subscriptions/processor.rb110
-rw-r--r--lib/solidus_subscriptions/testing_support/factories/installment_factory.rb4
2 files changed, 19 insertions, 95 deletions
diff --git a/lib/solidus_subscriptions/processor.rb b/lib/solidus_subscriptions/processor.rb
index d56816a..4547cec 100644
--- a/lib/solidus_subscriptions/processor.rb
+++ b/lib/solidus_subscriptions/processor.rb
@@ -1,116 +1,36 @@
# frozen_string_literal: true
-# This class is responsible for finding subscriptions and installments
-# which need to be processed. It will group them together by user and attempts
-# to process them together. Subscriptions will also be grouped by their
-# shiping address id.
-#
-# This class passes the reponsibility of actually creating the order off onto
-# the consolidated installment class.
-#
-# This class generates `ProcessInstallmentsJob`s
module SolidusSubscriptions
class Processor
class << self
- # Find all actionable subscriptions and intallments, group them together
- # by user, and schedule a processing job for the group as a batch
def run
- batched_users_to_be_processed.each { |batch| new(batch).build_jobs }
+ SolidusSubscriptions::Subscription.actionable.find_each(&method(:process_subscription))
+ SolidusSubscriptions::Installment.actionable.with_active_subscription.find_each(&method(:process_installment))
end
private
- def batched_users_to_be_processed
- subscriptions = SolidusSubscriptions::Subscription.arel_table
- installments = SolidusSubscriptions::Installment.arel_table
+ def process_subscription(subscription)
+ ActiveRecord::Base.transaction do
+ subscription.successive_skip_count = 0
+ subscription.advance_actionable_date
- ::Spree.user_class.
- joins(:subscriptions).
- joins(
- subscriptions.
- join(installments, Arel::Nodes::OuterJoin).
- on(subscriptions[:id].eq(installments[:subscription_id])).
- join_sources
- ).
- where(
- SolidusSubscriptions::Subscription.actionable.arel.constraints.reduce(:and).
- or(SolidusSubscriptions::Installment.actionable.with_active_subscription.arel.constraints.reduce(:and))
- ).
- distinct.
- find_in_batches
- end
- end
-
- # @return [Array<Spree.user_class>]
- attr_reader :users
-
- # Get a new instance of the SolidusSubscriptions::Processor
- #
- # @param users [Array<Spree.user_class>] A list of users with actionable
- # subscriptions or installments
- #
- # @return [SolidusSubscriptions::Processor]
- def initialize(users)
- @users = users
- @installments = {}
- end
-
- # Create `ProcessInstallmentsJob`s for the users used to initalize the
- # instance
- def build_jobs
- users.map do |user|
- installemts_by_address_and_user = installments(user).group_by do |i|
- [i.subscription.shipping_address_id, i.subscription.billing_address_id]
- end
-
- installemts_by_address_and_user.each_value do |grouped_installments|
- ProcessInstallmentsJob.perform_later grouped_installments.map(&:id)
- end
- end
- end
+ subscription.cancel! if subscription.pending_cancellation?
+ subscription.deactivate! if subscription.can_be_deactivated?
- private
-
- def subscriptions_by_id
- @subscriptions_by_id ||= Subscription.
- actionable.
- includes(:line_items, :user).
- where(user_id: user_ids).
- group_by(&:user_id)
- end
-
- def retry_installments
- @failed_installments ||= Installment.
- actionable.
- includes(:subscription).
- where(solidus_subscriptions_subscriptions: { user_id: user_ids }).
- group_by { |i| i.subscription.user_id }
- end
-
- def installments(user)
- @installments[user.id] ||= retry_installments.fetch(user.id, []) + new_installments(user)
- end
-
- def new_installments(user)
- ActiveRecord::Base.transaction do
- subscriptions_by_id.fetch(user.id, []).map do |sub|
- sub.successive_skip_count = 0
- sub.advance_actionable_date
- sub.cancel! if sub.pending_cancellation?
- sub.deactivate! if sub.can_be_deactivated?
if SolidusSubscriptions.configuration.clear_past_installments
- sub.installments.unfulfilled.each do |installment|
- installment.actionable_date = nil
- installment.save!
+ subscription.installments.unfulfilled.actionable.each do |installment|
+ installment.update!(actionable_date: nil)
end
end
- sub.installments.create!
+
+ subscription.installments.create!(actionable_date: Time.zone.now)
end
end
- end
- def user_ids
- @user_ids ||= users.map(&:id)
+ def process_installment(installment)
+ ProcessInstallmentsJob.perform_later(installment)
+ end
end
end
end
diff --git a/lib/solidus_subscriptions/testing_support/factories/installment_factory.rb b/lib/solidus_subscriptions/testing_support/factories/installment_factory.rb
index 2eb5069..20dcc04 100644
--- a/lib/solidus_subscriptions/testing_support/factories/installment_factory.rb
+++ b/lib/solidus_subscriptions/testing_support/factories/installment_factory.rb
@@ -21,5 +21,9 @@ FactoryBot.define do
[association(:installment_detail, :success, installment: @instance, order: order)]
end
end
+
+ trait :actionable do
+ actionable_date { Time.zone.now }
+ end
end
end