diff options
author | Brendan Deere <brendan@stembolt.com> | 2016-09-23 15:04:11 -0700 |
---|---|---|
committer | Brendan Deere <brendan@stembolt.com> | 2016-09-27 12:01:46 -0700 |
commit | 12780b8ed99f15da00c6959b62729762b35f4acc (patch) | |
tree | d30ccd9bd0f07912d3d7548cba829fe3e5fc7f88 /lib/solidus_subscriptions/processor.rb | |
parent | 20a87913c322e23bc142113d727ef7a4a419432c (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.rb | 90 |
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 |