solidus_core 3.1.9 → 3.2.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/helpers/spree/products_helper.rb +1 -1
- data/app/models/concerns/spree/active_storage_adapter/attachment.rb +23 -10
- data/app/models/concerns/spree/active_storage_adapter.rb +1 -1
- data/app/models/concerns/spree/default_price.rb +28 -4
- data/app/models/concerns/spree/user_address_book.rb +11 -1
- data/app/models/spree/adjustment.rb +1 -0
- data/app/models/spree/carton.rb +1 -1
- data/app/models/spree/option_value.rb +9 -0
- data/app/models/spree/order.rb +68 -29
- data/app/models/spree/order_contents.rb +2 -1
- data/app/models/spree/order_inventory.rb +1 -1
- data/app/models/spree/order_merger.rb +2 -2
- data/app/models/spree/order_taxation.rb +6 -4
- data/app/models/spree/order_updater.rb +4 -3
- data/app/models/spree/payment_method.rb +11 -0
- data/app/models/spree/price.rb +1 -1
- data/app/models/spree/product/scopes.rb +21 -3
- data/app/models/spree/product.rb +1 -1
- data/app/models/spree/promotion/actions/create_adjustment.rb +4 -0
- data/app/models/spree/promotion/actions/create_item_adjustments.rb +5 -6
- data/app/models/spree/promotion/rules/product.rb +20 -8
- data/app/models/spree/promotion/rules/store.rb +4 -0
- data/app/models/spree/promotion/rules/taxon.rb +4 -0
- data/app/models/spree/promotion/rules/user.rb +4 -0
- data/app/models/spree/promotion.rb +34 -23
- data/app/models/spree/promotion_action.rb +4 -0
- data/app/models/spree/promotion_code.rb +8 -4
- data/app/models/spree/promotion_handler/cart.rb +26 -6
- data/app/models/spree/promotion_rule.rb +5 -0
- data/app/models/spree/reimbursement.rb +2 -2
- data/app/models/spree/return_item.rb +1 -2
- data/app/models/spree/stock/allocator/on_hand_first.rb +2 -2
- data/app/models/spree/stock/quantifier.rb +12 -8
- data/app/models/spree/stock/simple_coordinator.rb +2 -1
- data/app/models/spree/tax/item_tax.rb +3 -2
- data/app/models/spree/tax/order_tax.rb +3 -1
- data/app/models/spree/tax/tax_location.rb +4 -7
- data/app/models/spree/tax_rate.rb +2 -0
- data/app/models/spree/variant/price_selector.rb +1 -18
- data/app/models/spree/variant.rb +2 -2
- data/app/subscribers/spree/mailer_subscriber.rb +4 -0
- data/app/subscribers/spree/order_mailer_subscriber.rb +35 -0
- data/config/locales/en.yml +7 -253
- data/db/migrate/20201127212108_add_type_before_removal_to_spree_payment_methods.rb +7 -0
- data/db/migrate/20220317165036_set_promotions_with_any_policy_to_all_if_possible.rb +20 -0
- data/lib/generators/solidus/install/install_generator/bundler_context.rb +97 -0
- data/lib/generators/solidus/install/install_generator/install_frontend.rb +50 -0
- data/lib/generators/solidus/install/install_generator/support_solidus_frontend_extraction.rb +48 -0
- data/lib/generators/solidus/install/install_generator.rb +56 -49
- data/lib/generators/solidus/install/templates/config/initializers/spree.rb.tt +6 -16
- data/lib/generators/solidus/install/templates/vendor/assets/javascripts/spree/backend/all.js +2 -2
- data/lib/spree/app_configuration.rb +29 -3
- data/lib/spree/bus.rb +20 -0
- data/lib/spree/core/controller_helpers/auth.rb +9 -1
- data/lib/spree/core/controller_helpers/current_host.rb +1 -3
- data/lib/spree/core/controller_helpers/order.rb +10 -10
- data/lib/spree/core/controller_helpers/search.rb +1 -1
- data/lib/spree/core/engine.rb +33 -8
- data/lib/spree/core/state_machines/order.rb +1 -1
- data/lib/spree/core/stock_configuration.rb +18 -0
- data/lib/spree/core/validators/email.rb +3 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +20 -0
- data/lib/spree/event/subscriber_registry.rb +4 -6
- data/lib/spree/event.rb +1 -1
- data/lib/spree/migrations.rb +1 -1
- data/lib/spree/permission_sets/default_customer.rb +8 -1
- data/lib/spree/permitted_attributes.rb +4 -4
- data/lib/spree/preferences/configuration.rb +34 -12
- data/lib/spree/preferences/preferable.rb +0 -5
- data/lib/spree/preferences/preferable_class_methods.rb +3 -3
- data/lib/spree/preferences/preference_differentiator.rb +2 -1
- data/lib/spree/preferences/static_model_preferences.rb +0 -2
- data/lib/spree/rails_compatibility.rb +99 -0
- data/lib/spree/testing_support/bus_helpers.rb +101 -0
- data/lib/spree/testing_support/common_rake.rb +47 -19
- data/lib/spree/testing_support/dummy_app/assets/javascripts/spree/backend/all.js +1 -1
- data/lib/spree/testing_support/dummy_app/assets/javascripts/spree/frontend/all.js +1 -1
- data/lib/spree/testing_support/dummy_app.rb +6 -2
- data/lib/spree/testing_support/factories/address_factory.rb +7 -2
- data/lib/spree/testing_support/factories/inventory_unit_factory.rb +1 -1
- data/lib/spree/testing_support/factories/order_factory.rb +8 -4
- data/lib/spree/testing_support/factories/product_factory.rb +4 -1
- data/lib/spree/testing_support/factories/store_credit_factory.rb +4 -4
- data/lib/spree/testing_support/factory_bot.rb +1 -1
- data/lib/spree/testing_support/order_walkthrough.rb +5 -4
- data/lib/spree/testing_support/silence_deprecations.rb +9 -0
- data/lib/tasks/payment_method.rake +29 -0
- data/lib/tasks/solidus/delete_prices_with_nil_amount.rake +2 -2
- data/lib/tasks/solidus/split_promotions_with_any_match_policy.rake +33 -0
- data/solidus_core.gemspec +6 -2
- metadata +71 -26
- data/lib/generators/solidus/install/templates/vendor/assets/javascripts/spree/frontend/all.js +0 -10
- data/lib/generators/solidus/install/templates/vendor/assets/stylesheets/spree/frontend/all.css +0 -9
@@ -8,6 +8,10 @@ module Spree
|
|
8
8
|
dependent: :destroy
|
9
9
|
has_many :taxons, through: :promotion_rule_taxons, class_name: 'Spree::Taxon'
|
10
10
|
|
11
|
+
def preload_relations
|
12
|
+
[:taxons]
|
13
|
+
end
|
14
|
+
|
11
15
|
MATCH_POLICIES = %w(any all none)
|
12
16
|
|
13
17
|
validates_inclusion_of :preferred_match_policy, in: MATCH_POLICIES
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module Spree
|
4
4
|
class Promotion < Spree::Base
|
5
5
|
MATCH_POLICIES = %w(all any)
|
6
|
+
|
6
7
|
UNACTIVATABLE_ORDER_STATES = ["complete", "awaiting_return", "returned"]
|
7
8
|
|
8
9
|
attr_reader :eligibility_errors
|
@@ -67,6 +68,19 @@ module Spree
|
|
67
68
|
).first
|
68
69
|
end
|
69
70
|
|
71
|
+
# All orders that have been discounted using this promotion
|
72
|
+
def discounted_orders
|
73
|
+
Spree::Order.
|
74
|
+
joins(:all_adjustments).
|
75
|
+
where(
|
76
|
+
spree_adjustments: {
|
77
|
+
source_type: "Spree::PromotionAction",
|
78
|
+
source_id: actions.map(&:id),
|
79
|
+
eligible: true
|
80
|
+
}
|
81
|
+
).distinct
|
82
|
+
end
|
83
|
+
|
70
84
|
def as_json(options = {})
|
71
85
|
options[:except] ||= :code
|
72
86
|
super
|
@@ -151,7 +165,7 @@ module Spree
|
|
151
165
|
return [] if rules.none?
|
152
166
|
|
153
167
|
eligible = lambda { |rule| rule.eligible?(promotable, options) }
|
154
|
-
specific_rules = rules.
|
168
|
+
specific_rules = rules.select { |rule| rule.applicable?(promotable) }
|
155
169
|
return [] if specific_rules.none?
|
156
170
|
|
157
171
|
if match_all?
|
@@ -163,6 +177,12 @@ module Spree
|
|
163
177
|
end
|
164
178
|
specific_rules
|
165
179
|
else
|
180
|
+
Spree::Deprecation.warn(
|
181
|
+
<<~WARN
|
182
|
+
Your promotion "#{name}" with ID #{id} has a match_policy of 'any'.
|
183
|
+
This is deprecated, please split the promotion into separate promotions for each rule.
|
184
|
+
WARN
|
185
|
+
)
|
166
186
|
unless specific_rules.any?(&eligible)
|
167
187
|
@eligibility_errors = specific_rules.map(&:eligibility_errors).detect(&:present?)
|
168
188
|
return nil
|
@@ -190,11 +210,11 @@ module Spree
|
|
190
210
|
# @param excluded_orders [Array<Spree::Order>] Orders to exclude from usage count
|
191
211
|
# @return [Integer] usage count
|
192
212
|
def usage_count(excluded_orders: [])
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
where(
|
197
|
-
count
|
213
|
+
discounted_orders.
|
214
|
+
complete.
|
215
|
+
where.not(id: [excluded_orders.map(&:id)]).
|
216
|
+
where.not(spree_orders: { state: :canceled }).
|
217
|
+
count
|
198
218
|
end
|
199
219
|
|
200
220
|
def line_item_actionable?(order, line_item, promotion_code: nil)
|
@@ -215,21 +235,12 @@ module Spree
|
|
215
235
|
end
|
216
236
|
|
217
237
|
def used_by?(user, excluded_orders = [])
|
218
|
-
|
219
|
-
|
220
|
-
:
|
221
|
-
:
|
222
|
-
|
223
|
-
|
224
|
-
spree_adjustments: {
|
225
|
-
source_type: "Spree::PromotionAction",
|
226
|
-
source_id: actions.map(&:id),
|
227
|
-
eligible: true
|
228
|
-
}
|
229
|
-
).where.not(
|
230
|
-
id: excluded_orders.map(&:id)
|
231
|
-
).any?
|
232
|
-
end
|
238
|
+
discounted_orders.
|
239
|
+
complete.
|
240
|
+
where.not(id: excluded_orders.map(&:id)).
|
241
|
+
where(user: user).
|
242
|
+
where.not(spree_orders: { state: :canceled }).
|
243
|
+
exists?
|
233
244
|
end
|
234
245
|
|
235
246
|
# Removes a promotion and any adjustments or other side effects from an
|
@@ -251,9 +262,9 @@ module Spree
|
|
251
262
|
def blacklisted?(promotable)
|
252
263
|
case promotable
|
253
264
|
when Spree::LineItem
|
254
|
-
!promotable.product.promotionable?
|
265
|
+
!promotable.variant.product.promotionable?
|
255
266
|
when Spree::Order
|
256
|
-
promotable.line_items.
|
267
|
+
promotable.line_items.any? { |line_item| !line_item.variant.product.promotionable? }
|
257
268
|
end
|
258
269
|
end
|
259
270
|
|
@@ -16,6 +16,10 @@ module Spree
|
|
16
16
|
scope :of_type, ->(type) { where(type: Array.wrap(type).map(&:to_s)) }
|
17
17
|
scope :shipping, -> { of_type(Spree::Config.environment.promotions.shipping_actions.to_a) }
|
18
18
|
|
19
|
+
def preload_relations
|
20
|
+
[]
|
21
|
+
end
|
22
|
+
|
19
23
|
# Updates the state of the order or performs some other action depending on
|
20
24
|
# the subclass options will contain the payload from the event that
|
21
25
|
# activated the promotion. This will include the key :user which allows
|
@@ -28,10 +28,14 @@ class Spree::PromotionCode < Spree::Base
|
|
28
28
|
# @param excluded_orders [Array<Spree::Order>] Orders to exclude from usage count
|
29
29
|
# @return [Integer] usage count
|
30
30
|
def usage_count(excluded_orders: [])
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
promotion.
|
32
|
+
discounted_orders.
|
33
|
+
complete.
|
34
|
+
where.not(spree_orders: { state: :canceled }).
|
35
|
+
joins(:order_promotions).
|
36
|
+
where(spree_orders_promotions: { promotion_code_id: self.id }).
|
37
|
+
where.not(id: excluded_orders.map(&:id)).
|
38
|
+
count
|
35
39
|
end
|
36
40
|
|
37
41
|
def usage_limit
|
@@ -33,23 +33,43 @@ module Spree
|
|
33
33
|
private
|
34
34
|
|
35
35
|
def promotions
|
36
|
-
connected_order_promotions | sale_promotions
|
36
|
+
promos = connected_order_promotions | sale_promotions
|
37
|
+
promos.flat_map(&:promotion_actions).group_by(&:preload_relations).each do |preload_relations, actions|
|
38
|
+
preload(records: actions, associations: preload_relations)
|
39
|
+
end
|
40
|
+
promos.flat_map(&:promotion_rules).group_by(&:preload_relations).each do |preload_relations, rules|
|
41
|
+
preload(records: rules, associations: preload_relations)
|
42
|
+
end
|
43
|
+
promos
|
44
|
+
end
|
45
|
+
|
46
|
+
def preload(records:, associations:)
|
47
|
+
if Rails::VERSION::MAJOR >= 7
|
48
|
+
ActiveRecord::Associations::Preloader.new(records: records, associations: associations).call
|
49
|
+
else
|
50
|
+
ActiveRecord::Associations::Preloader.new.preload(records, associations)
|
51
|
+
end
|
37
52
|
end
|
38
53
|
|
39
54
|
def connected_order_promotions
|
40
|
-
|
41
|
-
joins(:order_promotions).
|
42
|
-
where(spree_orders_promotions: { order_id: order.id }).readonly(false).to_a
|
55
|
+
order.promotions.active.includes(promotion_includes)
|
43
56
|
end
|
44
57
|
|
45
58
|
def sale_promotions
|
46
|
-
Spree::Promotion.where(apply_automatically: true).active.includes(
|
59
|
+
Spree::Promotion.where(apply_automatically: true).active.includes(promotion_includes)
|
47
60
|
end
|
48
61
|
|
49
62
|
def promotion_code(promotion)
|
50
|
-
order_promotion =
|
63
|
+
order_promotion = order.order_promotions.detect { |op| op.promotion_id == promotion.id }
|
51
64
|
order_promotion.present? ? order_promotion.promotion_code : nil
|
52
65
|
end
|
66
|
+
|
67
|
+
def promotion_includes
|
68
|
+
[
|
69
|
+
:promotion_rules,
|
70
|
+
:promotion_actions,
|
71
|
+
]
|
72
|
+
end
|
53
73
|
end
|
54
74
|
end
|
55
75
|
end
|
@@ -14,9 +14,14 @@ module Spree
|
|
14
14
|
validates :promotion, presence: true
|
15
15
|
validate :unique_per_promotion, on: :create
|
16
16
|
|
17
|
+
def preload_relations
|
18
|
+
[]
|
19
|
+
end
|
20
|
+
|
17
21
|
def self.for(promotable)
|
18
22
|
all.select { |rule| rule.applicable?(promotable) }
|
19
23
|
end
|
24
|
+
deprecate :for, "Please select promotion rules by their applicable status on the promotable instead."
|
20
25
|
|
21
26
|
def applicable?(_promotable)
|
22
27
|
raise NotImplementedError, "applicable? should be implemented in a sub-class of Spree::PromotionRule"
|
@@ -92,10 +92,10 @@ module Spree
|
|
92
92
|
|
93
93
|
if unpaid_amount_within_tolerance?
|
94
94
|
reimbursed!
|
95
|
-
Spree::
|
95
|
+
Spree::Bus.publish :reimbursement_reimbursed, reimbursement: self
|
96
96
|
else
|
97
97
|
errored!
|
98
|
-
Spree::
|
98
|
+
Spree::Bus.publish :reimbursement_errored, reimbursement: self
|
99
99
|
end
|
100
100
|
|
101
101
|
if errored?
|
@@ -30,7 +30,7 @@ module Spree
|
|
30
30
|
self.refund_amount_calculator = Calculator::Returns::DefaultRefundAmount
|
31
31
|
|
32
32
|
belongs_to :return_authorization, inverse_of: :return_items, optional: true
|
33
|
-
belongs_to :inventory_unit, inverse_of: :return_items
|
33
|
+
belongs_to :inventory_unit, inverse_of: :return_items
|
34
34
|
belongs_to :exchange_variant, class_name: 'Spree::Variant', optional: true
|
35
35
|
belongs_to :exchange_inventory_unit, class_name: 'Spree::InventoryUnit', inverse_of: :original_return_item, optional: true
|
36
36
|
belongs_to :customer_return, inverse_of: :return_items, optional: true
|
@@ -42,7 +42,6 @@ module Spree
|
|
42
42
|
validate :eligible_exchange_variant
|
43
43
|
validate :belongs_to_same_customer_order
|
44
44
|
validate :validate_acceptance_status_for_reimbursement
|
45
|
-
validates :inventory_unit, presence: true
|
46
45
|
validate :validate_no_other_completed_return_items
|
47
46
|
|
48
47
|
after_create :cancel_others, unless: :cancelled?
|
@@ -7,11 +7,11 @@ module Spree
|
|
7
7
|
def allocate_inventory(desired)
|
8
8
|
# Allocate any available on hand inventory
|
9
9
|
on_hand = allocate_on_hand(desired)
|
10
|
-
desired -= on_hand.values.
|
10
|
+
desired -= on_hand.values.reduce(&:+) if on_hand.present?
|
11
11
|
|
12
12
|
# Allocate remaining desired inventory from backorders
|
13
13
|
backordered = allocate_backordered(desired)
|
14
|
-
desired -= backordered.values.
|
14
|
+
desired -= backordered.values.reduce(&:+) if backordered.present?
|
15
15
|
|
16
16
|
# If all works at this point desired must be empty
|
17
17
|
[on_hand, backordered, desired]
|
@@ -6,14 +6,18 @@ module Spree
|
|
6
6
|
attr_reader :stock_items
|
7
7
|
|
8
8
|
# @param [Variant] variant The variant to check inventory for.
|
9
|
-
# @param [StockLocation, Integer]
|
10
|
-
|
9
|
+
# @param [StockLocation, Integer] stock_location_or_id
|
10
|
+
# The stock_location or stock location ID to check inventory in.
|
11
|
+
# If unspecified it will check inventory in all available StockLocations
|
12
|
+
def initialize(variant, stock_location_or_id = nil)
|
11
13
|
@variant = variant
|
12
|
-
@stock_items =
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
@stock_items = variant.stock_items.select do |stock_item|
|
15
|
+
if stock_location_or_id
|
16
|
+
stock_item.stock_location == stock_location_or_id ||
|
17
|
+
stock_item.stock_location_id == stock_location_or_id
|
18
|
+
else
|
19
|
+
stock_item.stock_location.active?
|
20
|
+
end
|
17
21
|
end
|
18
22
|
end
|
19
23
|
|
@@ -23,7 +27,7 @@ module Spree
|
|
23
27
|
# inventory is not tracked on the variant.
|
24
28
|
def total_on_hand
|
25
29
|
if @variant.should_track_inventory?
|
26
|
-
stock_items.sum(
|
30
|
+
stock_items.sum(&:count_on_hand)
|
27
31
|
else
|
28
32
|
Float::INFINITY
|
29
33
|
end
|
@@ -24,7 +24,8 @@ module Spree
|
|
24
24
|
|
25
25
|
def initialize(order, inventory_units = nil)
|
26
26
|
@order = order
|
27
|
-
@inventory_units =
|
27
|
+
@inventory_units =
|
28
|
+
inventory_units || Spree::Config.stock.inventory_unit_builder_class.new(order).units
|
28
29
|
@splitters = Spree::Config.environment.stock_splitters
|
29
30
|
|
30
31
|
filtered_stock_locations = Spree::Config.stock.location_filter_class.new(Spree::StockLocation.all, @order).filter
|
@@ -5,9 +5,10 @@ module Spree
|
|
5
5
|
# Simple object used to hold tax data for an item.
|
6
6
|
#
|
7
7
|
# This generic object will hold the amount of tax that should be applied to
|
8
|
-
# an item. (Either a {Spree::LineItem} or a {Spree::Shipment}.)
|
8
|
+
# an item. (Either a {Spree::Order}, a {Spree::LineItem} or a {Spree::Shipment}.)
|
9
9
|
#
|
10
|
-
# @attr_reader [Integer] item_id the {Spree::LineItem} or {Spree::Shipment} ID
|
10
|
+
# @attr_reader [Integer] item_id the {Spree::LineItem} or {Spree::Shipment} ID.
|
11
|
+
# Or blank if an order-level tax.
|
11
12
|
# @attr_reader [String] label information about the taxes
|
12
13
|
# @attr_reader [Spree::TaxRate] tax_rate will be used as the source for tax
|
13
14
|
# adjustments
|
@@ -8,13 +8,15 @@ module Spree
|
|
8
8
|
# adjustments on an order.
|
9
9
|
#
|
10
10
|
# @attr_reader [Integer] order_id the {Spree::Order} these taxes apply to
|
11
|
+
# @attr_reader [Array<Spree::Tax::ItemTax>] order_taxes an array of tax
|
12
|
+
# data for the order
|
11
13
|
# @attr_reader [Array<Spree::Tax::ItemTax>] line_item_taxes an array of
|
12
14
|
# tax data for order's line items
|
13
15
|
# @attr_reader [Array<Spree::Tax::ItemTax>] shipment_taxes an array of
|
14
16
|
# tax data for the order's shipments
|
15
17
|
class OrderTax
|
16
18
|
include ActiveModel::Model
|
17
|
-
attr_accessor :order_id, :line_item_taxes, :shipment_taxes
|
19
|
+
attr_accessor :order_id, :order_taxes, :line_item_taxes, :shipment_taxes
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -8,7 +8,7 @@ module Spree
|
|
8
8
|
# @attr_reader [Integer] country_id the ID of a Spree::Country object
|
9
9
|
# @attr_reader [Integer] state_id the ID of a Spree::State object
|
10
10
|
class TaxLocation
|
11
|
-
attr_reader :
|
11
|
+
attr_reader :country, :state
|
12
12
|
|
13
13
|
# Create a new TaxLocation object
|
14
14
|
#
|
@@ -19,18 +19,15 @@ module Spree
|
|
19
19
|
#
|
20
20
|
# @return [Spree::Tax::TaxLocation] a Spree::Tax::TaxLocation object
|
21
21
|
def initialize(country: nil, state: nil)
|
22
|
-
@
|
23
|
-
@state_id = state && state.id
|
22
|
+
@country, @state = country, state
|
24
23
|
end
|
24
|
+
delegate :id, to: :state, prefix: true, allow_nil: true
|
25
|
+
delegate :id, to: :country, prefix: true, allow_nil: true
|
25
26
|
|
26
27
|
def ==(other)
|
27
28
|
state_id == other.state_id && country_id == other.country_id
|
28
29
|
end
|
29
30
|
|
30
|
-
def country
|
31
|
-
Spree::Country.find_by(id: country_id)
|
32
|
-
end
|
33
|
-
|
34
31
|
def empty?
|
35
32
|
country_id.nil? && state_id.nil?
|
36
33
|
end
|
@@ -27,6 +27,8 @@ module Spree
|
|
27
27
|
|
28
28
|
validates :amount, presence: true, numericality: true
|
29
29
|
|
30
|
+
self.whitelisted_ransackable_associations = %w[tax_categories zone]
|
31
|
+
|
30
32
|
# Finds all tax rates whose zones match a given address
|
31
33
|
scope :for_address, ->(address) { joins(:zone).merge(Spree::Zone.for_address(address)) }
|
32
34
|
scope :for_country,
|
@@ -39,29 +39,12 @@ module Spree
|
|
39
39
|
# @param [Spree::Variant::PricingOptions] price_options Pricing Options to abide by
|
40
40
|
# @return [Spree::Price, nil] The most specific price for this set of pricing options.
|
41
41
|
def price_for_options(price_options)
|
42
|
-
|
42
|
+
variant.currently_valid_prices.detect do |price|
|
43
43
|
(price.country_iso == price_options.desired_attributes[:country_iso] ||
|
44
44
|
price.country_iso.nil?
|
45
45
|
) && price.currency == price_options.desired_attributes[:currency]
|
46
46
|
end
|
47
47
|
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
# Returns `#prices` prioritized for being considered as default price
|
52
|
-
#
|
53
|
-
# @return [Array<Spree::Price>]
|
54
|
-
def sorted_prices_for(variant)
|
55
|
-
variant.prices.select do |price|
|
56
|
-
variant.discarded? || price.kept?
|
57
|
-
end.sort_by do |price|
|
58
|
-
[
|
59
|
-
price.country_iso.nil? ? 0 : 1,
|
60
|
-
price.updated_at || Time.zone.now,
|
61
|
-
price.id || Float::INFINITY,
|
62
|
-
]
|
63
|
-
end.reverse
|
64
|
-
end
|
65
48
|
end
|
66
49
|
end
|
67
50
|
end
|
data/app/models/spree/variant.rb
CHANGED
@@ -23,6 +23,7 @@ module Spree
|
|
23
23
|
after_discard do
|
24
24
|
stock_items.discard_all
|
25
25
|
images.destroy_all
|
26
|
+
prices.discard_all
|
26
27
|
end
|
27
28
|
|
28
29
|
attr_writer :rebuild_vat_prices
|
@@ -51,7 +52,6 @@ module Spree
|
|
51
52
|
has_many :images, -> { order(:position) }, as: :viewable, dependent: :destroy, class_name: "Spree::Image"
|
52
53
|
|
53
54
|
has_many :prices,
|
54
|
-
-> { with_discarded },
|
55
55
|
class_name: 'Spree::Price',
|
56
56
|
dependent: :destroy,
|
57
57
|
inverse_of: :variant,
|
@@ -66,7 +66,7 @@ module Spree
|
|
66
66
|
|
67
67
|
validates :cost_price, numericality: { greater_than_or_equal_to: 0, allow_nil: true }
|
68
68
|
validates :price, numericality: { greater_than_or_equal_to: 0, allow_nil: true }
|
69
|
-
validates_uniqueness_of :sku, allow_blank: true, case_sensitive: true, if: :enforce_unique_sku?
|
69
|
+
validates_uniqueness_of :sku, allow_blank: true, case_sensitive: true, conditions: -> { where(deleted_at: nil) }, if: :enforce_unique_sku?
|
70
70
|
|
71
71
|
after_create :create_stock_items
|
72
72
|
after_create :set_position
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
# Mailing after events on a {Spree::Order}
|
5
|
+
class OrderMailerSubscriber
|
6
|
+
include Omnes::Subscriber
|
7
|
+
|
8
|
+
handle :order_finalized,
|
9
|
+
with: :send_confirmation_email,
|
10
|
+
id: :spree_order_mailer_send_confirmation_email
|
11
|
+
|
12
|
+
handle :reimbursement_reimbursed,
|
13
|
+
with: :send_reimbursement_email,
|
14
|
+
id: :spree_order_mailer_send_reimbursement_email
|
15
|
+
|
16
|
+
# Sends confirmation email to the user
|
17
|
+
#
|
18
|
+
# @param event [Omnes::UnstructuredEvent]
|
19
|
+
def send_confirmation_email(event)
|
20
|
+
order = event[:order]
|
21
|
+
unless order.confirmation_delivered?
|
22
|
+
Spree::Config.order_mailer_class.confirm_email(order).deliver_later
|
23
|
+
order.update_column(:confirmation_delivered, true)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Sends reimbursement email to the user
|
28
|
+
#
|
29
|
+
# @param event [Omnes::UnstructuredEvent]
|
30
|
+
def send_reimbursement_email(event)
|
31
|
+
reimbursement = event[:reimbursement]
|
32
|
+
Spree::Config.reimbursement_mailer_class.reimbursement_email(reimbursement.id).deliver_later
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|