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,15 +1,15 @@
|
|
|
1
|
-
# Spree::Orders may contain many subscription_line_items. When the order is
|
|
2
|
-
# finalized these subscription_line_items are converted into subscritpions.
|
|
3
|
-
# The order needs to be able to get a list of associated subscription_line_items
|
|
4
|
-
# to be able to populate the full subscriptions.
|
|
5
|
-
module Spree
|
|
6
|
-
module Orders
|
|
7
|
-
module SubscriptionLineItemsAssociation
|
|
8
|
-
def self.prepended(base)
|
|
9
|
-
base.has_many :subscription_line_items, through: :line_items
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
Spree::Order.prepend Spree::Orders::SubscriptionLineItemsAssociation
|
|
1
|
+
# Spree::Orders may contain many subscription_line_items. When the order is
|
|
2
|
+
# finalized these subscription_line_items are converted into subscritpions.
|
|
3
|
+
# The order needs to be able to get a list of associated subscription_line_items
|
|
4
|
+
# to be able to populate the full subscriptions.
|
|
5
|
+
module Spree
|
|
6
|
+
module Orders
|
|
7
|
+
module SubscriptionLineItemsAssociation
|
|
8
|
+
def self.prepended(base)
|
|
9
|
+
base.has_many :subscription_line_items, through: :line_items
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
Spree::Order.prepend Spree::Orders::SubscriptionLineItemsAssociation
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Products
|
|
3
|
-
module Subscribable
|
|
4
|
-
def self.prepended(klass)
|
|
5
|
-
klass.delegate :"subscribable", :"subscribable=", to: :find_or_build_master
|
|
6
|
-
end
|
|
7
|
-
end
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
Spree::Product.prepend Spree::Products::Subscribable
|
|
1
|
+
module Spree
|
|
2
|
+
module Products
|
|
3
|
+
module Subscribable
|
|
4
|
+
def self.prepended(klass)
|
|
5
|
+
klass.delegate :"subscribable", :"subscribable=", to: :find_or_build_master
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Spree::Product.prepend Spree::Products::Subscribable
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
# Spree::Users maintain a list of the subscriptions associated with them
|
|
2
|
-
module Spree
|
|
3
|
-
module Users
|
|
4
|
-
module HaveManySubscritptions
|
|
5
|
-
def self.prepended(base)
|
|
6
|
-
base.has_many(
|
|
7
|
-
:subscriptions,
|
|
8
|
-
class_name: 'SolidusSubscriptions::Subscription',
|
|
9
|
-
foreign_key: 'user_id'
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
base.accepts_nested_attributes_for :subscriptions
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
Spree.user_class.prepend(Spree::Users::HaveManySubscritptions)
|
|
1
|
+
# Spree::Users maintain a list of the subscriptions associated with them
|
|
2
|
+
module Spree
|
|
3
|
+
module Users
|
|
4
|
+
module HaveManySubscritptions
|
|
5
|
+
def self.prepended(base)
|
|
6
|
+
base.has_many(
|
|
7
|
+
:subscriptions,
|
|
8
|
+
class_name: 'SolidusSubscriptions::Subscription',
|
|
9
|
+
foreign_key: 'user_id'
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
base.accepts_nested_attributes_for :subscriptions
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
Spree.user_class.prepend(Spree::Users::HaveManySubscritptions)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Variants
|
|
3
|
-
module VariantPrettyName
|
|
4
|
-
def pretty_name
|
|
5
|
-
name = product.name
|
|
6
|
-
name += " - #{options_text}" if options_text.present?
|
|
7
|
-
name
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
Spree::Variant.prepend Spree::Variants::VariantPrettyName
|
|
1
|
+
module Spree
|
|
2
|
+
module Variants
|
|
3
|
+
module VariantPrettyName
|
|
4
|
+
def pretty_name
|
|
5
|
+
name = product.name
|
|
6
|
+
name += " - #{options_text}" if options_text.present?
|
|
7
|
+
name
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
Spree::Variant.prepend Spree::Variants::VariantPrettyName
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
# This job is responsible for creating a consolidated installment from a
|
|
2
|
-
# list of installments and processing it.
|
|
3
|
-
|
|
4
|
-
module SolidusSubscriptions
|
|
5
|
-
class ProcessInstallmentsJob < ActiveJob::Base
|
|
6
|
-
queue_as Config.processing_queue
|
|
7
|
-
|
|
8
|
-
# Process a collection of installments
|
|
9
|
-
#
|
|
10
|
-
# @param installment_ids [Array<Integer>] The ids of the
|
|
11
|
-
# installments to be processed together and fulfilled by the same order
|
|
12
|
-
#
|
|
13
|
-
# @return [Spree::Order] The order which fulfills the list of installments
|
|
14
|
-
def perform(installment_ids)
|
|
15
|
-
return if installment_ids.empty?
|
|
16
|
-
|
|
17
|
-
installments = SolidusSubscriptions::Installment.where(id: installment_ids).
|
|
18
|
-
includes(subscription: [:line_items, :user])
|
|
19
|
-
Checkout.new(installments).process
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
1
|
+
# This job is responsible for creating a consolidated installment from a
|
|
2
|
+
# list of installments and processing it.
|
|
3
|
+
|
|
4
|
+
module SolidusSubscriptions
|
|
5
|
+
class ProcessInstallmentsJob < ActiveJob::Base
|
|
6
|
+
queue_as Config.processing_queue
|
|
7
|
+
|
|
8
|
+
# Process a collection of installments
|
|
9
|
+
#
|
|
10
|
+
# @param installment_ids [Array<Integer>] The ids of the
|
|
11
|
+
# installments to be processed together and fulfilled by the same order
|
|
12
|
+
#
|
|
13
|
+
# @return [Spree::Order] The order which fulfills the list of installments
|
|
14
|
+
def perform(installment_ids)
|
|
15
|
+
return if installment_ids.empty?
|
|
16
|
+
|
|
17
|
+
installments = SolidusSubscriptions::Installment.where(id: installment_ids).
|
|
18
|
+
includes(subscription: [:line_items, :user])
|
|
19
|
+
Checkout.new(installments).process
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -1,141 +1,141 @@
|
|
|
1
|
-
# This class takes a collection of installments and populates a new spree
|
|
2
|
-
# order with the correct contents based on the subscriptions associated to the
|
|
3
|
-
# intallments. This is to group together subscriptions being
|
|
4
|
-
# processed on the same day for a specific user
|
|
5
|
-
module SolidusSubscriptions
|
|
6
|
-
class Checkout
|
|
7
|
-
# @return [Array<Installment>] The collection of installments to be used
|
|
8
|
-
# when generating a new order
|
|
9
|
-
attr_reader :installments
|
|
10
|
-
|
|
11
|
-
delegate :user, to: :subscription
|
|
12
|
-
|
|
13
|
-
# Get a new instance of a Checkout
|
|
14
|
-
#
|
|
15
|
-
# @param installments [Array<Installment>] The collection of installments
|
|
16
|
-
# to be used when generating a new order
|
|
17
|
-
def initialize(installments)
|
|
18
|
-
@installments = installments
|
|
19
|
-
raise UserMismatchError.new(installments) if different_owners?
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Generate a new Spree::Order based on the information associated to the
|
|
23
|
-
# installments
|
|
24
|
-
#
|
|
25
|
-
# @return [Spree::Order]
|
|
26
|
-
def process
|
|
27
|
-
populate
|
|
28
|
-
|
|
29
|
-
# Installments are removed and set for future processing if they are
|
|
30
|
-
# out of stock. If there are no line items left there is nothing to do
|
|
31
|
-
return if installments.empty?
|
|
32
|
-
|
|
33
|
-
if checkout
|
|
34
|
-
Config.success_dispatcher_class.new(installments, order).dispatch
|
|
35
|
-
return order
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# A new order will only have 1 payment that we created
|
|
39
|
-
if order.payments.any?(&:failed?)
|
|
40
|
-
Config.payment_failed_dispatcher_class.new(installments, order).dispatch
|
|
41
|
-
installments.clear
|
|
42
|
-
nil
|
|
43
|
-
end
|
|
44
|
-
ensure
|
|
45
|
-
# Any installments that failed to be processed will be reprocessed
|
|
46
|
-
unfulfilled_installments = installments.select(&:unfulfilled?)
|
|
47
|
-
if unfulfilled_installments.any?
|
|
48
|
-
Config.failure_dispatcher_class.
|
|
49
|
-
new(unfulfilled_installments, order).dispatch
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# The order fulfilling the consolidated installment
|
|
54
|
-
#
|
|
55
|
-
# @return [Spree::Order]
|
|
56
|
-
def order
|
|
57
|
-
@order ||= Spree::Order.create(
|
|
58
|
-
user: user,
|
|
59
|
-
email: user.email,
|
|
60
|
-
store: subscription.store || Spree::Store.default,
|
|
61
|
-
subscription_order: true
|
|
62
|
-
)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
private
|
|
66
|
-
|
|
67
|
-
def checkout
|
|
68
|
-
order.update!
|
|
69
|
-
apply_promotions
|
|
70
|
-
|
|
71
|
-
order.checkout_steps.count.times do
|
|
72
|
-
order.ship_address = ship_address if order.state == "address"
|
|
73
|
-
create_payment if order.state == "payment"
|
|
74
|
-
order.next! if order.next_transition.present?
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Do this as a separate "quiet" transition so that it returns true or
|
|
78
|
-
# false rather than raising a failed transition error
|
|
79
|
-
order.complete
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def populate
|
|
83
|
-
unfulfilled_installments = []
|
|
84
|
-
|
|
85
|
-
order_line_items = installments.flat_map do |installment|
|
|
86
|
-
line_items = installment.line_item_builder.spree_line_items
|
|
87
|
-
|
|
88
|
-
unfulfilled_installments.push(installment) if line_items.empty?
|
|
89
|
-
|
|
90
|
-
line_items
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Remove installments which had no stock from the active list
|
|
94
|
-
# They will be reprocessed later
|
|
95
|
-
@installments -= unfulfilled_installments
|
|
96
|
-
if unfulfilled_installments.any?
|
|
97
|
-
Config.out_of_stock_dispatcher_class.new(unfulfilled_installments).dispatch
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
return if installments.empty?
|
|
101
|
-
order_builder.add_line_items(order_line_items)
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def order_builder
|
|
105
|
-
@order_builder ||= OrderBuilder.new(order)
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def subscription
|
|
109
|
-
installments.first.subscription
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def ship_address
|
|
113
|
-
subscription.shipping_address || user.ship_address
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def active_card
|
|
117
|
-
if SolidusSupport.solidus_gem_version < Gem::Version.new("2.2.0")
|
|
118
|
-
user.credit_cards.default.last
|
|
119
|
-
else
|
|
120
|
-
user.wallet.default_wallet_payment_source.payment_source
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def create_payment
|
|
125
|
-
order.payments.create(
|
|
126
|
-
source: active_card,
|
|
127
|
-
amount: order.total,
|
|
128
|
-
payment_method: Config.default_gateway
|
|
129
|
-
)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def apply_promotions
|
|
133
|
-
Spree::PromotionHandler::Cart.new(order).activate
|
|
134
|
-
order.updater.update # reload totals
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def different_owners?
|
|
138
|
-
installments.map { |i| i.subscription.user }.uniq.length > 1
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|
|
1
|
+
# This class takes a collection of installments and populates a new spree
|
|
2
|
+
# order with the correct contents based on the subscriptions associated to the
|
|
3
|
+
# intallments. This is to group together subscriptions being
|
|
4
|
+
# processed on the same day for a specific user
|
|
5
|
+
module SolidusSubscriptions
|
|
6
|
+
class Checkout
|
|
7
|
+
# @return [Array<Installment>] The collection of installments to be used
|
|
8
|
+
# when generating a new order
|
|
9
|
+
attr_reader :installments
|
|
10
|
+
|
|
11
|
+
delegate :user, to: :subscription
|
|
12
|
+
|
|
13
|
+
# Get a new instance of a Checkout
|
|
14
|
+
#
|
|
15
|
+
# @param installments [Array<Installment>] The collection of installments
|
|
16
|
+
# to be used when generating a new order
|
|
17
|
+
def initialize(installments)
|
|
18
|
+
@installments = installments
|
|
19
|
+
raise UserMismatchError.new(installments) if different_owners?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Generate a new Spree::Order based on the information associated to the
|
|
23
|
+
# installments
|
|
24
|
+
#
|
|
25
|
+
# @return [Spree::Order]
|
|
26
|
+
def process
|
|
27
|
+
populate
|
|
28
|
+
|
|
29
|
+
# Installments are removed and set for future processing if they are
|
|
30
|
+
# out of stock. If there are no line items left there is nothing to do
|
|
31
|
+
return if installments.empty?
|
|
32
|
+
|
|
33
|
+
if checkout
|
|
34
|
+
Config.success_dispatcher_class.new(installments, order).dispatch
|
|
35
|
+
return order
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# A new order will only have 1 payment that we created
|
|
39
|
+
if order.payments.any?(&:failed?)
|
|
40
|
+
Config.payment_failed_dispatcher_class.new(installments, order).dispatch
|
|
41
|
+
installments.clear
|
|
42
|
+
nil
|
|
43
|
+
end
|
|
44
|
+
ensure
|
|
45
|
+
# Any installments that failed to be processed will be reprocessed
|
|
46
|
+
unfulfilled_installments = installments.select(&:unfulfilled?)
|
|
47
|
+
if unfulfilled_installments.any?
|
|
48
|
+
Config.failure_dispatcher_class.
|
|
49
|
+
new(unfulfilled_installments, order).dispatch
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# The order fulfilling the consolidated installment
|
|
54
|
+
#
|
|
55
|
+
# @return [Spree::Order]
|
|
56
|
+
def order
|
|
57
|
+
@order ||= Spree::Order.create(
|
|
58
|
+
user: user,
|
|
59
|
+
email: user.email,
|
|
60
|
+
store: subscription.store || Spree::Store.default,
|
|
61
|
+
subscription_order: true
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def checkout
|
|
68
|
+
order.update!
|
|
69
|
+
apply_promotions
|
|
70
|
+
|
|
71
|
+
order.checkout_steps.count.times do
|
|
72
|
+
order.ship_address = ship_address if order.state == "address"
|
|
73
|
+
create_payment if order.state == "payment"
|
|
74
|
+
order.next! if order.next_transition.present?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Do this as a separate "quiet" transition so that it returns true or
|
|
78
|
+
# false rather than raising a failed transition error
|
|
79
|
+
order.complete
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def populate
|
|
83
|
+
unfulfilled_installments = []
|
|
84
|
+
|
|
85
|
+
order_line_items = installments.flat_map do |installment|
|
|
86
|
+
line_items = installment.line_item_builder.spree_line_items
|
|
87
|
+
|
|
88
|
+
unfulfilled_installments.push(installment) if line_items.empty?
|
|
89
|
+
|
|
90
|
+
line_items
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Remove installments which had no stock from the active list
|
|
94
|
+
# They will be reprocessed later
|
|
95
|
+
@installments -= unfulfilled_installments
|
|
96
|
+
if unfulfilled_installments.any?
|
|
97
|
+
Config.out_of_stock_dispatcher_class.new(unfulfilled_installments).dispatch
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
return if installments.empty?
|
|
101
|
+
order_builder.add_line_items(order_line_items)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def order_builder
|
|
105
|
+
@order_builder ||= OrderBuilder.new(order)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def subscription
|
|
109
|
+
installments.first.subscription
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def ship_address
|
|
113
|
+
subscription.shipping_address || user.ship_address
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def active_card
|
|
117
|
+
if SolidusSupport.solidus_gem_version < Gem::Version.new("2.2.0")
|
|
118
|
+
user.credit_cards.default.last
|
|
119
|
+
else
|
|
120
|
+
user.wallet.default_wallet_payment_source.payment_source
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def create_payment
|
|
125
|
+
order.payments.create(
|
|
126
|
+
source: active_card,
|
|
127
|
+
amount: order.total,
|
|
128
|
+
payment_method: Config.default_gateway
|
|
129
|
+
)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def apply_promotions
|
|
133
|
+
Spree::PromotionHandler::Cart.new(order).activate
|
|
134
|
+
order.updater.update # reload totals
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def different_owners?
|
|
138
|
+
installments.map { |i| i.subscription.user }.uniq.length > 1
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|