blob: 97b39dfc1079e814f29cd815f7b1fd1e1f0d61de (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
|