solidus_subscriptions-alpha 0.0.3 → 0.0.4
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/LICENSE +26 -26
- data/README.md +130 -130
- data/Rakefile +28 -28
- data/app/assets/javascripts/spree/backend/solidus_subscriptions.js +1 -1
- data/app/assets/javascripts/spree/frontend/solidus_subscriptions.js +1 -1
- data/app/assets/stylesheets/spree/backend/solidus_subscriptions.css +4 -4
- data/app/assets/stylesheets/spree/frontend/solidus_subscriptions.css +4 -4
- data/app/controllers/solidus_subscriptions/api/v1/line_items_controller.rb +35 -35
- data/app/controllers/solidus_subscriptions/api/v1/subscriptions_controller.rb +44 -44
- data/app/controllers/spree/admin/subscriptions_controller.rb +66 -66
- data/app/decorators/spree/controllers/api/line_items/create_subscription_line_items.rb +28 -28
- data/app/decorators/spree/controllers/orders/create_subscription_line_items.rb +33 -33
- data/app/decorators/spree/line_items/subscription_line_items_association.rb +22 -22
- data/app/decorators/spree/orders/after_create.rb +15 -15
- data/app/decorators/spree/orders/finalize_creates_subscriptions.rb +19 -19
- data/app/decorators/spree/orders/subscription_line_items_association.rb +15 -15
- data/app/decorators/spree/products/subscribable_decorator.rb +11 -11
- data/app/decorators/spree/users/have_many_subscriptions.rb +18 -18
- data/app/decorators/spree/variant_pretty_name.rb +13 -13
- data/app/jobs/solidus_subscriptions/process_installments_job.rb +22 -22
- data/app/models/solidus_subscriptions/checkout.rb +141 -141
- data/app/models/solidus_subscriptions/dispatcher.rb +32 -32
- data/app/models/solidus_subscriptions/failure_dispatcher.rb +19 -19
- data/app/models/solidus_subscriptions/installment.rb +126 -126
- data/app/models/solidus_subscriptions/installment_detail.rb +23 -23
- data/app/models/solidus_subscriptions/interval.rb +24 -24
- data/app/models/solidus_subscriptions/line_item.rb +98 -98
- data/app/models/solidus_subscriptions/line_item_builder.rb +44 -44
- data/app/models/solidus_subscriptions/order_builder.rb +40 -40
- data/app/models/solidus_subscriptions/out_of_stock_dispatcher.rb +19 -19
- data/app/models/solidus_subscriptions/payment_failed_dispatcher.rb +23 -23
- data/app/models/solidus_subscriptions/subscription.rb +217 -217
- data/app/models/solidus_subscriptions/subscription_generator.rb +60 -60
- data/app/models/solidus_subscriptions/subscription_line_item_builder.rb +21 -21
- data/app/models/solidus_subscriptions/subscription_order_promotion_rule.rb +25 -25
- data/app/models/solidus_subscriptions/subscription_promotion_rule.rb +38 -38
- data/app/models/solidus_subscriptions/success_dispatcher.rb +16 -16
- data/app/models/solidus_subscriptions/unsubscribable_error.rb +17 -17
- data/app/models/solidus_subscriptions/user_mismatch_error.rb +15 -15
- data/app/overrides/views/admin_subscribable_checkbox.rb +13 -13
- data/app/overrides/views/admin_subscriptions_menu_link.rb +8 -8
- data/app/overrides/views/subscription_line_item_fields.rb +6 -6
- data/app/views/spree/admin/products/_subscribable_checkbox.html.erb +8 -8
- data/app/views/spree/admin/promotions/rules/_subscription_order_promotion_rule.html.erb +0 -0
- data/app/views/spree/admin/promotions/rules/_subscription_promotion_rule.html.erb +0 -0
- data/app/views/spree/admin/shared/_no_objects_found.html.erb +4 -4
- data/app/views/spree/admin/shared/_subscription_tab.html.erb +3 -3
- data/app/views/spree/admin/solidus_subscriptions/subscriptions/_subscription.html.erb +66 -66
- data/app/views/spree/admin/subscriptions/_form.html.erb +81 -81
- data/app/views/spree/admin/subscriptions/_legacy_form.html.erb +81 -81
- data/app/views/spree/admin/subscriptions/_legacy_sidebar.html.erb +28 -28
- data/app/views/spree/admin/subscriptions/edit.html.erb +21 -21
- data/app/views/spree/admin/subscriptions/index.html.erb +119 -119
- data/app/views/spree/admin/subscriptions/new.html.erb +9 -9
- data/app/views/spree/admin/variants/_subscribable_checkbox.html.erb +6 -6
- data/app/views/spree/frontend/products/_subscription_line_item_fields.html.erb +30 -30
- data/config/locales/en.yml +91 -91
- data/config/routes.rb +25 -25
- data/db/migrate/20160825164850_create_solidus_subscriptions_subscriptions.rb +11 -11
- data/db/migrate/20160825173548_create_solidus_subscriptions_line_items.rb +17 -17
- data/db/migrate/20160825202248_create_solidus_subscriptions_installments.rb +23 -23
- data/db/migrate/20160825211202_create_solidus_subscriptions_installment_details.rb +22 -22
- data/db/migrate/20160825214240_add_subscribable_to_spree_variants.rb +5 -5
- data/db/migrate/20160829201653_change_subscription_line_items_installments_to_max_installments.rb +5 -5
- data/db/migrate/20160902220242_remove_state_from_solidus_susbscriptions_installment_details.rb +5 -5
- data/db/migrate/20160902220604_add_successful_to_solidus_subscriptions_installment_details.rb +5 -5
- data/db/migrate/20160902221218_add_message_to_solidus_subscriptions_installment_details.rb +5 -5
- data/db/migrate/20160922164101_add_interval_length_and_units_to_subscription_line_items.rb +8 -8
- data/db/migrate/20161006191003_add_skip_count_to_solidus_subscriptions_subscriptions.rb +5 -5
- data/db/migrate/20161006191127_add_successive_skip_count_to_solidus_subscriptions_subscriptions.rb +5 -5
- data/db/migrate/20161014212649_allow_spree_line_item_id_to_be_null.rb +5 -5
- data/db/migrate/20161017155749_add_order_id_to_solidus_subscriptions_installment_details.rb +6 -6
- data/db/migrate/20161017175509_remove_order_id_from_solidus_subscriptions_installments.rb +6 -6
- data/db/migrate/20161017201944_add_subscription_order_to_spree_orders.rb +5 -5
- data/db/migrate/20161221155142_add_store_to_solidus_subscriptions_subscriptions.rb +6 -6
- data/db/migrate/20161223152905_add_address_id_to_solidus_subscriptions_subscriptions.rb +7 -7
- data/db/migrate/20170106224713_change_line_item_max_installments_to_end_date.rb +6 -6
- data/db/migrate/20170111224458_change_subscription_actionable_date_to_datetime.rb +5 -5
- data/db/migrate/20170111232801_change_inteval_actionable_date_to_datetime.rb +5 -5
- data/db/migrate/20170112012407_add_config_options_to_subscriptions.rb +7 -7
- data/lib/generators/solidus_subscriptions/install/install_generator.rb +30 -30
- data/lib/solidus_subscriptions.rb +6 -6
- data/lib/solidus_subscriptions/ability.rb +19 -19
- data/lib/solidus_subscriptions/config.rb +97 -97
- data/lib/solidus_subscriptions/engine.rb +56 -56
- data/lib/solidus_subscriptions/permitted_attributes.rb +36 -36
- data/lib/solidus_subscriptions/processor.rb +108 -108
- data/lib/solidus_subscriptions/testing_support/factories.rb +5 -5
- data/lib/solidus_subscriptions/testing_support/factories/installment_detail_factory.rb +7 -7
- data/lib/solidus_subscriptions/testing_support/factories/installment_factory.rb +21 -21
- data/lib/solidus_subscriptions/testing_support/factories/line_item_factory.rb +18 -18
- data/lib/solidus_subscriptions/testing_support/factories/spree/line_item_factory.rb +17 -17
- data/lib/solidus_subscriptions/testing_support/factories/spree/order_factory.rb +18 -18
- data/lib/solidus_subscriptions/testing_support/factories/spree_modification_factory.rb +8 -8
- data/lib/solidus_subscriptions/testing_support/factories/subscription_factory.rb +43 -43
- data/lib/solidus_subscriptions/version.rb +3 -3
- data/lib/tasks/process_subscriptions.rake +6 -6
- metadata +3 -3
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
module SolidusSubscriptions
|
|
2
|
-
class Engine < Rails::Engine
|
|
3
|
-
require 'spree/core'
|
|
4
|
-
require 'solidus_subscriptions/permitted_attributes'
|
|
5
|
-
require 'solidus_subscriptions/config'
|
|
6
|
-
require 'solidus_subscriptions/processor'
|
|
7
|
-
|
|
8
|
-
isolate_namespace SolidusSubscriptions
|
|
9
|
-
engine_name 'solidus_subscriptions'
|
|
10
|
-
|
|
11
|
-
# use rspec for tests
|
|
12
|
-
config.generators do |g|
|
|
13
|
-
g.test_framework :rspec
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
config.autoload_paths << config.root.join('app', 'jobs')
|
|
17
|
-
|
|
18
|
-
initializer 'configure spree subcription permitted attributes', after: 'require subscription lib helpers' do
|
|
19
|
-
PermittedAttributes.update_spree_permiteed_attributes
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
initializer 'solidus_subscriptions.configs', before: "require subscription lib helpers" do
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
initializer 'register_subscription_promotion_rule', after: 'spree.promo.register.promotion.rules' do |app|
|
|
26
|
-
app.config.spree.promotions.rules << 'SolidusSubscriptions::SubscriptionPromotionRule'
|
|
27
|
-
app.config.spree.promotions.rules << 'SolidusSubscriptions::SubscriptionOrderPromotionRule'
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
initializer 'subscriptions_backend' do
|
|
31
|
-
next unless Spree::Backend::Config.respond_to?(:menu_items)
|
|
32
|
-
Spree::Backend::Config.configure do |config|
|
|
33
|
-
config.menu_items << config.class::MenuItem.new(
|
|
34
|
-
[:subscriptions],
|
|
35
|
-
'repeat',
|
|
36
|
-
url: :admin_subscriptions_path,
|
|
37
|
-
condition: ->{ can?(:admin, SolidusSubscriptions::Subscription) }
|
|
38
|
-
)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def self.activate
|
|
43
|
-
Dir.glob(File.join(File.dirname(__FILE__), '../../app/decorators/**/*.rb')) do |c|
|
|
44
|
-
Rails.configuration.cache_classes ? require(c) : load(c)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
Spree::Ability.register_ability(SolidusSubscriptions::Ability)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
config.to_prepare(&method(:activate).to_proc)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def self.table_name_prefix
|
|
54
|
-
'solidus_subscriptions_'
|
|
55
|
-
end
|
|
56
|
-
end
|
|
1
|
+
module SolidusSubscriptions
|
|
2
|
+
class Engine < Rails::Engine
|
|
3
|
+
require 'spree/core'
|
|
4
|
+
require 'solidus_subscriptions/permitted_attributes'
|
|
5
|
+
require 'solidus_subscriptions/config'
|
|
6
|
+
require 'solidus_subscriptions/processor'
|
|
7
|
+
|
|
8
|
+
isolate_namespace SolidusSubscriptions
|
|
9
|
+
engine_name 'solidus_subscriptions'
|
|
10
|
+
|
|
11
|
+
# use rspec for tests
|
|
12
|
+
config.generators do |g|
|
|
13
|
+
g.test_framework :rspec
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
config.autoload_paths << config.root.join('app', 'jobs')
|
|
17
|
+
|
|
18
|
+
initializer 'configure spree subcription permitted attributes', after: 'require subscription lib helpers' do
|
|
19
|
+
PermittedAttributes.update_spree_permiteed_attributes
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
initializer 'solidus_subscriptions.configs', before: "require subscription lib helpers" do
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
initializer 'register_subscription_promotion_rule', after: 'spree.promo.register.promotion.rules' do |app|
|
|
26
|
+
app.config.spree.promotions.rules << 'SolidusSubscriptions::SubscriptionPromotionRule'
|
|
27
|
+
app.config.spree.promotions.rules << 'SolidusSubscriptions::SubscriptionOrderPromotionRule'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
initializer 'subscriptions_backend' do
|
|
31
|
+
next unless Spree::Backend::Config.respond_to?(:menu_items)
|
|
32
|
+
Spree::Backend::Config.configure do |config|
|
|
33
|
+
config.menu_items << config.class::MenuItem.new(
|
|
34
|
+
[:subscriptions],
|
|
35
|
+
'repeat',
|
|
36
|
+
url: :admin_subscriptions_path,
|
|
37
|
+
condition: ->{ can?(:admin, SolidusSubscriptions::Subscription) }
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.activate
|
|
43
|
+
Dir.glob(File.join(File.dirname(__FILE__), '../../app/decorators/**/*.rb')) do |c|
|
|
44
|
+
Rails.configuration.cache_classes ? require(c) : load(c)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
Spree::Ability.register_ability(SolidusSubscriptions::Ability)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
config.to_prepare(&method(:activate).to_proc)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.table_name_prefix
|
|
54
|
+
'solidus_subscriptions_'
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
# This module is responsible for managing what attributes can be updated
|
|
2
|
-
# through the api. It also overrides Spree::Permitted attributes to allow the
|
|
3
|
-
# solidus api to accept nested params for subscription models as well
|
|
4
|
-
module SolidusSubscriptions
|
|
5
|
-
module PermittedAttributes
|
|
6
|
-
class << self
|
|
7
|
-
def update_spree_permiteed_attributes
|
|
8
|
-
Spree::PermittedAttributes.line_item_attributes << {
|
|
9
|
-
subscription_line_items_attributes: nested(
|
|
10
|
-
subscription_line_item_attributes
|
|
11
|
-
)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
Spree::PermittedAttributes.user_attributes << {
|
|
15
|
-
subscriptions_attributes: nested(subscription_attributes)
|
|
16
|
-
}
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def subscription_line_item_attributes
|
|
20
|
-
[Config.subscription_line_item_attributes]
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def subscription_attributes
|
|
24
|
-
Config.subscription_attributes | [
|
|
25
|
-
{ line_items_attributes: nested(subscription_line_item_attributes) - [:subscribable_id] }
|
|
26
|
-
]
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
private
|
|
30
|
-
|
|
31
|
-
def nested(attributes)
|
|
32
|
-
attributes | [:id]
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
1
|
+
# This module is responsible for managing what attributes can be updated
|
|
2
|
+
# through the api. It also overrides Spree::Permitted attributes to allow the
|
|
3
|
+
# solidus api to accept nested params for subscription models as well
|
|
4
|
+
module SolidusSubscriptions
|
|
5
|
+
module PermittedAttributes
|
|
6
|
+
class << self
|
|
7
|
+
def update_spree_permiteed_attributes
|
|
8
|
+
Spree::PermittedAttributes.line_item_attributes << {
|
|
9
|
+
subscription_line_items_attributes: nested(
|
|
10
|
+
subscription_line_item_attributes
|
|
11
|
+
)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
Spree::PermittedAttributes.user_attributes << {
|
|
15
|
+
subscriptions_attributes: nested(subscription_attributes)
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def subscription_line_item_attributes
|
|
20
|
+
[Config.subscription_line_item_attributes]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def subscription_attributes
|
|
24
|
+
Config.subscription_attributes | [
|
|
25
|
+
{ line_items_attributes: nested(subscription_line_item_attributes) - [:subscribable_id] }
|
|
26
|
+
]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def nested(attributes)
|
|
32
|
+
attributes | [:id]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -1,108 +1,108 @@
|
|
|
1
|
-
# This class is responsible for finding subscriptions and installments
|
|
2
|
-
# which need to be processed. It will group them together by user and attempts
|
|
3
|
-
# to process them together. Subscriptions will also be grouped by their
|
|
4
|
-
# shiping address id.
|
|
5
|
-
#
|
|
6
|
-
# This class passes the reponsibility of actually creating the order off onto
|
|
7
|
-
# the consolidated installment class.
|
|
8
|
-
#
|
|
9
|
-
# This class generates `ProcessInstallmentsJob`s
|
|
10
|
-
module SolidusSubscriptions
|
|
11
|
-
class Processor
|
|
12
|
-
class << self
|
|
13
|
-
# Find all actionable subscriptions and intallments, group them together
|
|
14
|
-
# by user, and schedule a processing job for the group as a batch
|
|
15
|
-
def run
|
|
16
|
-
batched_users_to_be_processed.each { |batch| new(batch).build_jobs }
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
def batched_users_to_be_processed
|
|
22
|
-
subscriptions = SolidusSubscriptions::Subscription.arel_table
|
|
23
|
-
installments = SolidusSubscriptions::Installment.arel_table
|
|
24
|
-
|
|
25
|
-
Spree::User.
|
|
26
|
-
joins(:subscriptions).
|
|
27
|
-
joins(
|
|
28
|
-
subscriptions.
|
|
29
|
-
join(installments, Arel::Nodes::OuterJoin).
|
|
30
|
-
on(subscriptions[:id].eq(installments[:subscription_id])).
|
|
31
|
-
join_sources
|
|
32
|
-
).
|
|
33
|
-
where(
|
|
34
|
-
SolidusSubscriptions::Subscription.actionable.arel.constraints.reduce(:and).
|
|
35
|
-
or(SolidusSubscriptions::Installment.actionable.arel.constraints.reduce(:and))
|
|
36
|
-
).
|
|
37
|
-
distinct.
|
|
38
|
-
find_in_batches
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# @return [Array<Spree.user_class>]
|
|
43
|
-
attr_reader :users
|
|
44
|
-
|
|
45
|
-
# Get a new instance of the SolidusSubscriptions::Processor
|
|
46
|
-
#
|
|
47
|
-
# @param users [Array<Spree.user_class>] A list of users with actionable
|
|
48
|
-
# subscriptions or installments
|
|
49
|
-
#
|
|
50
|
-
# @return [SolidusSubscriptions::Processor]
|
|
51
|
-
def initialize(users)
|
|
52
|
-
@users = users
|
|
53
|
-
@installments = {}
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# Create `ProcessInstallmentsJob`s for the users used to initalize the
|
|
57
|
-
# instance
|
|
58
|
-
def build_jobs
|
|
59
|
-
users.map do |user|
|
|
60
|
-
installemts_by_address_and_user = installments(user).group_by do |i|
|
|
61
|
-
i.subscription.shipping_address_id
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
installemts_by_address_and_user.values.each do |grouped_installments|
|
|
65
|
-
ProcessInstallmentsJob.perform_later grouped_installments.map(&:id)
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
private
|
|
71
|
-
|
|
72
|
-
def subscriptions_by_id
|
|
73
|
-
@subscriptions_by_id ||= Subscription.
|
|
74
|
-
actionable.
|
|
75
|
-
includes(:line_items, :user).
|
|
76
|
-
where(user_id: user_ids).
|
|
77
|
-
group_by(&:user_id)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def retry_installments
|
|
81
|
-
@failed_installments ||= Installment.
|
|
82
|
-
actionable.
|
|
83
|
-
includes(:subscription).
|
|
84
|
-
where(solidus_subscriptions_subscriptions: { user_id: user_ids }).
|
|
85
|
-
group_by { |i| i.subscription.user_id }
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def installments(user)
|
|
89
|
-
@installments[user.id] ||= retry_installments.fetch(user.id, []) + new_installments(user)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def new_installments(user)
|
|
93
|
-
ActiveRecord::Base.transaction do
|
|
94
|
-
subscriptions_by_id.fetch(user.id, []).map do |sub|
|
|
95
|
-
sub.successive_skip_count = 0
|
|
96
|
-
sub.advance_actionable_date
|
|
97
|
-
sub.cancel! if sub.pending_cancellation?
|
|
98
|
-
sub.deactivate! if sub.can_be_deactivated?
|
|
99
|
-
sub.installments.create!
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def user_ids
|
|
105
|
-
@user_ids ||= users.map(&:id)
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
1
|
+
# This class is responsible for finding subscriptions and installments
|
|
2
|
+
# which need to be processed. It will group them together by user and attempts
|
|
3
|
+
# to process them together. Subscriptions will also be grouped by their
|
|
4
|
+
# shiping address id.
|
|
5
|
+
#
|
|
6
|
+
# This class passes the reponsibility of actually creating the order off onto
|
|
7
|
+
# the consolidated installment class.
|
|
8
|
+
#
|
|
9
|
+
# This class generates `ProcessInstallmentsJob`s
|
|
10
|
+
module SolidusSubscriptions
|
|
11
|
+
class Processor
|
|
12
|
+
class << self
|
|
13
|
+
# Find all actionable subscriptions and intallments, group them together
|
|
14
|
+
# by user, and schedule a processing job for the group as a batch
|
|
15
|
+
def run
|
|
16
|
+
batched_users_to_be_processed.each { |batch| new(batch).build_jobs }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def batched_users_to_be_processed
|
|
22
|
+
subscriptions = SolidusSubscriptions::Subscription.arel_table
|
|
23
|
+
installments = SolidusSubscriptions::Installment.arel_table
|
|
24
|
+
|
|
25
|
+
Spree::User.
|
|
26
|
+
joins(:subscriptions).
|
|
27
|
+
joins(
|
|
28
|
+
subscriptions.
|
|
29
|
+
join(installments, Arel::Nodes::OuterJoin).
|
|
30
|
+
on(subscriptions[:id].eq(installments[:subscription_id])).
|
|
31
|
+
join_sources
|
|
32
|
+
).
|
|
33
|
+
where(
|
|
34
|
+
SolidusSubscriptions::Subscription.actionable.arel.constraints.reduce(:and).
|
|
35
|
+
or(SolidusSubscriptions::Installment.actionable.arel.constraints.reduce(:and))
|
|
36
|
+
).
|
|
37
|
+
distinct.
|
|
38
|
+
find_in_batches
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @return [Array<Spree.user_class>]
|
|
43
|
+
attr_reader :users
|
|
44
|
+
|
|
45
|
+
# Get a new instance of the SolidusSubscriptions::Processor
|
|
46
|
+
#
|
|
47
|
+
# @param users [Array<Spree.user_class>] A list of users with actionable
|
|
48
|
+
# subscriptions or installments
|
|
49
|
+
#
|
|
50
|
+
# @return [SolidusSubscriptions::Processor]
|
|
51
|
+
def initialize(users)
|
|
52
|
+
@users = users
|
|
53
|
+
@installments = {}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Create `ProcessInstallmentsJob`s for the users used to initalize the
|
|
57
|
+
# instance
|
|
58
|
+
def build_jobs
|
|
59
|
+
users.map do |user|
|
|
60
|
+
installemts_by_address_and_user = installments(user).group_by do |i|
|
|
61
|
+
i.subscription.shipping_address_id
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
installemts_by_address_and_user.values.each do |grouped_installments|
|
|
65
|
+
ProcessInstallmentsJob.perform_later grouped_installments.map(&:id)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def subscriptions_by_id
|
|
73
|
+
@subscriptions_by_id ||= Subscription.
|
|
74
|
+
actionable.
|
|
75
|
+
includes(:line_items, :user).
|
|
76
|
+
where(user_id: user_ids).
|
|
77
|
+
group_by(&:user_id)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def retry_installments
|
|
81
|
+
@failed_installments ||= Installment.
|
|
82
|
+
actionable.
|
|
83
|
+
includes(:subscription).
|
|
84
|
+
where(solidus_subscriptions_subscriptions: { user_id: user_ids }).
|
|
85
|
+
group_by { |i| i.subscription.user_id }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def installments(user)
|
|
89
|
+
@installments[user.id] ||= retry_installments.fetch(user.id, []) + new_installments(user)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def new_installments(user)
|
|
93
|
+
ActiveRecord::Base.transaction do
|
|
94
|
+
subscriptions_by_id.fetch(user.id, []).map do |sub|
|
|
95
|
+
sub.successive_skip_count = 0
|
|
96
|
+
sub.advance_actionable_date
|
|
97
|
+
sub.cancel! if sub.pending_cancellation?
|
|
98
|
+
sub.deactivate! if sub.can_be_deactivated?
|
|
99
|
+
sub.installments.create!
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def user_ids
|
|
105
|
+
@user_ids ||= users.map(&:id)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
require 'factory_girl'
|
|
2
|
-
require 'spree/testing_support/factories'
|
|
3
|
-
|
|
4
|
-
factory_path = "#{File.dirname(__FILE__)}/factories/**/*_factory.rb"
|
|
5
|
-
Dir[factory_path].each { |f| require File.expand_path(f) }
|
|
1
|
+
require 'factory_girl'
|
|
2
|
+
require 'spree/testing_support/factories'
|
|
3
|
+
|
|
4
|
+
factory_path = "#{File.dirname(__FILE__)}/factories/**/*_factory.rb"
|
|
5
|
+
Dir[factory_path].each { |f| require File.expand_path(f) }
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
FactoryGirl.define do
|
|
2
|
-
factory :installment_detail, class: 'SolidusSubscriptions::InstallmentDetail' do
|
|
3
|
-
installment
|
|
4
|
-
|
|
5
|
-
trait(:success) { success true }
|
|
6
|
-
end
|
|
7
|
-
end
|
|
1
|
+
FactoryGirl.define do
|
|
2
|
+
factory :installment_detail, class: 'SolidusSubscriptions::InstallmentDetail' do
|
|
3
|
+
installment
|
|
4
|
+
|
|
5
|
+
trait(:success) { success true }
|
|
6
|
+
end
|
|
7
|
+
end
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
FactoryGirl.define do
|
|
2
|
-
factory :installment, class: 'SolidusSubscriptions::Installment' do
|
|
3
|
-
transient { subscription_traits [] }
|
|
4
|
-
subscription { build :subscription, :with_line_item, *subscription_traits }
|
|
5
|
-
|
|
6
|
-
trait :failed do
|
|
7
|
-
actionable_date { Time.zone.yesterday }
|
|
8
|
-
details { build_list(:installment_detail, 1, installment: @instance) }
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
trait :success do
|
|
12
|
-
transient do
|
|
13
|
-
order { create :completed_order_with_totals }
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
details do
|
|
17
|
-
build_list(:installment_detail, 1, :success, installment: @instance, order: order)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
1
|
+
FactoryGirl.define do
|
|
2
|
+
factory :installment, class: 'SolidusSubscriptions::Installment' do
|
|
3
|
+
transient { subscription_traits [] }
|
|
4
|
+
subscription { build :subscription, :with_line_item, *subscription_traits }
|
|
5
|
+
|
|
6
|
+
trait :failed do
|
|
7
|
+
actionable_date { Time.zone.yesterday }
|
|
8
|
+
details { build_list(:installment_detail, 1, installment: @instance) }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
trait :success do
|
|
12
|
+
transient do
|
|
13
|
+
order { create :completed_order_with_totals }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
details do
|
|
17
|
+
build_list(:installment_detail, 1, :success, installment: @instance, order: order)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|