summaryrefslogtreecommitdiff
path: root/lib/solidus_subscriptions/processor.rb
diff options
context:
space:
mode:
authorBrendan Deere <brendan@stembolt.com>2016-09-23 15:04:11 -0700
committerBrendan Deere <brendan@stembolt.com>2016-09-27 12:01:46 -0700
commit12780b8ed99f15da00c6959b62729762b35f4acc (patch)
treed30ccd9bd0f07912d3d7548cba829fe3e5fc7f88 /lib/solidus_subscriptions/processor.rb
parent20a87913c322e23bc142113d727ef7a4a419432c (diff)
Add Processor
This class looks up all actionable subscriptions and installments, groups them by user and schedules them to be reprocessed.
Diffstat (limited to 'lib/solidus_subscriptions/processor.rb')
-rw-r--r--lib/solidus_subscriptions/processor.rb90
1 files changed, 90 insertions, 0 deletions
diff --git a/lib/solidus_subscriptions/processor.rb b/lib/solidus_subscriptions/processor.rb
new file mode 100644
index 0000000..97b39df
--- /dev/null
+++ b/lib/solidus_subscriptions/processor.rb
@@ -0,0 +1,90 @@
+# 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.
+#
+# 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 }
+ end
+
+ private
+
+ def batched_users_to_be_processed
+ subscriptions = Subscription.arel_table
+ installments = Installment.arel_table
+
+ Spree::User.
+ joins(:subscriptions).
+ joins(
+ subscriptions.
+ join(installments, Arel::Nodes::OuterJoin).
+ on(subscriptions[:id].eq(installments[:subscription_id])).
+ join_sources
+ ).
+ where(
+ Subscription.actionable.arel.constraints.reduce(:and).
+ or(Installment.actionable.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 { |user| ProcessInstallmentsJob.perform_later installments(user) }
+ end
+
+ private
+
+ def subscriptions_by_id
+ @subscriptions_by_id ||= Subscription.
+ actionable.
+ 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)
+ subscriptions_by_id.fetch(user.id, []).map { |sub| sub.installments.create! }
+ end
+
+ def user_ids
+ @user_ids ||= users.map(&:id)
+ end
+ end
+end