spree_core 4.1.8 → 4.2.0.rc1
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/app/controllers/spree/base_controller.rb +1 -0
- data/app/finders/spree/addresses/find.rb +17 -0
- data/app/helpers/spree/base_helper.rb +60 -13
- data/app/helpers/spree/mail_helper.rb +29 -0
- data/app/helpers/spree/products_helper.rb +2 -1
- data/app/mailers/spree/base_mailer.rb +17 -3
- data/app/mailers/spree/order_mailer.rb +11 -2
- data/app/mailers/spree/reimbursement_mailer.rb +4 -2
- data/app/mailers/spree/shipment_mailer.rb +4 -2
- data/app/models/concerns/spree/default_price.rb +2 -1
- data/app/models/concerns/spree/user_methods.rb +11 -5
- data/app/models/concerns/spree/user_payment_source.rb +1 -1
- data/app/models/spree/address.rb +13 -1
- data/app/models/spree/app_configuration.rb +5 -0
- data/app/models/spree/app_dependencies.rb +7 -1
- data/app/models/spree/credit_card.rb +5 -0
- data/app/models/spree/line_item.rb +12 -2
- data/app/models/spree/option_type.rb +5 -1
- data/app/models/spree/order.rb +33 -7
- data/app/models/spree/order/payments.rb +10 -2
- data/app/models/spree/preferences/store.rb +1 -1
- data/app/models/spree/price.rb +26 -2
- data/app/models/spree/product.rb +17 -7
- data/app/models/spree/promotion.rb +6 -0
- data/app/models/spree/promotion_handler/coupon.rb +1 -1
- data/app/models/spree/promotion_handler/promotion_duplicator.rb +9 -3
- data/app/models/spree/reimbursement.rb +2 -0
- data/app/models/spree/shipment.rb +2 -5
- data/app/models/spree/stock_location.rb +13 -2
- data/app/models/spree/store.rb +22 -2
- data/app/models/spree/variant.rb +20 -3
- data/app/presenters/spree/variant_presenter.rb +9 -1
- data/app/presenters/spree/variants/option_types_presenter.rb +1 -0
- data/app/services/spree/account/addresses/base.rb +39 -0
- data/app/services/spree/account/addresses/create.rb +18 -0
- data/app/services/spree/account/addresses/update.rb +18 -0
- data/app/services/spree/checkout/update.rb +13 -2
- data/app/views/layouts/spree/base_mailer.html.erb +45 -40
- data/app/views/spree/order_mailer/cancel_email.html.erb +19 -25
- data/app/views/spree/order_mailer/cancel_email.text.erb +24 -2
- data/app/views/spree/order_mailer/confirm_email.html.erb +18 -65
- data/app/views/spree/order_mailer/confirm_email.text.erb +2 -1
- data/app/views/spree/order_mailer/store_owner_notification_email.html.erb +23 -0
- data/app/views/spree/order_mailer/store_owner_notification_email.text.erb +38 -0
- data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +53 -58
- data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +3 -1
- data/app/views/spree/shared/_base_mailer_footer.html.erb +6 -14
- data/app/views/spree/shared/_base_mailer_header.html.erb +12 -32
- data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +293 -625
- data/app/views/spree/shared/_purchased_items_table.html.erb +60 -0
- data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +13 -0
- data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +27 -0
- data/app/views/spree/shared/purchased_items_table/_subtotal.html.erb +13 -0
- data/app/views/spree/shared/purchased_items_table/_total.html.erb +13 -0
- data/app/views/spree/shipment_mailer/shipped_email.html.erb +31 -36
- data/app/views/spree/shipment_mailer/shipped_email.text.erb +2 -1
- data/config/initializers/assets.rb +1 -0
- data/config/locales/en.yml +123 -16
- data/db/default/spree/countries.rb +10 -4
- data/db/default/spree/states.rb +42 -5
- data/db/default/spree/stores.rb +17 -12
- data/db/default/spree/zones.rb +1 -1
- data/db/migrate/20140309033438_create_store_from_preferences.rb +1 -1
- data/db/migrate/20191017121054_add_supported_currencies_to_store.rb +10 -0
- data/db/migrate/20200102141311_add_social_to_spree_stores.rb +3 -0
- data/db/migrate/20200308210757_add_default_locale_to_spree_store.rb +7 -0
- data/db/migrate/20200310145140_add_customer_support_email_to_spree_store.rb +7 -0
- data/db/migrate/20200421095017_add_compare_at_amount_to_spree_prices.rb +7 -0
- data/db/migrate/20200423123001_add_default_country_id_to_spree_store.rb +9 -0
- data/db/migrate/20200430072209_add_footer_fields_to_spree_stores.rb +8 -0
- data/db/migrate/20200513154939_add_show_property_to_spree_product_properties.rb +5 -0
- data/db/migrate/20200607161221_add_store_owner_order_notification_delivered_to_spree_orders.rb +7 -0
- data/db/migrate/20200607161222_add_new_order_notifications_email_to_spree_stores.rb +7 -0
- data/db/migrate/20200610113542_add_label_to_spree_addresses.rb +5 -0
- data/db/migrate/20200826075557_add_unique_index_on_taxon_id_and_product_id_to_spree_products_taxons.rb +5 -0
- data/db/migrate/20201013084504_add_seo_robots_to_spree_stores.rb +5 -0
- data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/backend/all.js +0 -2
- data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/frontend/all.js +0 -2
- data/lib/generators/spree/mailers_preview/mailers_preview_generator.rb +23 -0
- data/lib/generators/spree/mailers_preview/templates/mailers/previews/order_preview.rb +13 -0
- data/lib/generators/spree/mailers_preview/templates/mailers/previews/reimbursement_preview.rb +5 -0
- data/lib/generators/spree/mailers_preview/templates/mailers/previews/shipment_preview.rb +5 -0
- data/lib/generators/spree/mailers_preview/templates/mailers/previews/user_preview.rb +11 -0
- data/lib/spree/core.rb +2 -0
- data/lib/spree/core/controller_helpers/common.rb +1 -0
- data/lib/spree/core/controller_helpers/currency_helpers.rb +15 -0
- data/lib/spree/core/controller_helpers/order.rb +9 -4
- data/lib/spree/core/controller_helpers/store.rb +12 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/permitted_attributes.rb +8 -5
- data/lib/spree/testing_support/authorization_helpers.rb +7 -4
- data/lib/spree/testing_support/factories/store_factory.rb +11 -8
- data/spree_core.gemspec +5 -4
- data/vendor/assets/javascripts/cleave.js +1669 -0
- metadata +55 -12
- data/app/views/spree/order_mailer/_adjustment.html.erb +0 -8
- data/app/views/spree/order_mailer/_subtotal.html.erb +0 -8
- data/app/views/spree/order_mailer/_total.html.erb +0 -8
data/app/models/spree/order.rb
CHANGED
@@ -22,7 +22,7 @@ module Spree
|
|
22
22
|
money_methods :outstanding_balance, :item_total, :adjustment_total,
|
23
23
|
:included_tax_total, :additional_tax_total, :tax_total,
|
24
24
|
:shipment_total, :promo_total, :total,
|
25
|
-
:cart_promo_total
|
25
|
+
:cart_promo_total, :pre_tax_item_amount, :pre_tax_total
|
26
26
|
|
27
27
|
alias display_ship_total display_shipment_total
|
28
28
|
alias_attribute :ship_total, :shipment_total
|
@@ -174,7 +174,12 @@ module Spree
|
|
174
174
|
|
175
175
|
# Sum of all line item amounts pre-tax
|
176
176
|
def pre_tax_item_amount
|
177
|
-
line_items.
|
177
|
+
line_items.sum(:pre_tax_amount)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Sum of all line item and shipment pre-tax
|
181
|
+
def pre_tax_total
|
182
|
+
pre_tax_item_amount + shipments.sum(:pre_tax_amount)
|
178
183
|
end
|
179
184
|
|
180
185
|
def shipping_discount
|
@@ -297,15 +302,15 @@ module Spree
|
|
297
302
|
def outstanding_balance
|
298
303
|
if canceled?
|
299
304
|
-1 * payment_total
|
300
|
-
elsif refunds.exists?
|
301
|
-
# If refund has happened add it back to total to prevent balance_due payment state
|
302
|
-
# See: https://github.com/spree/spree/issues/6229 & https://github.com/spree/spree/issues/8136
|
303
|
-
total - (payment_total + refunds.sum(:amount))
|
304
305
|
else
|
305
|
-
total - payment_total
|
306
|
+
total - (payment_total + reimbursement_paid_total)
|
306
307
|
end
|
307
308
|
end
|
308
309
|
|
310
|
+
def reimbursement_paid_total
|
311
|
+
reimbursements.sum(&:paid_amount)
|
312
|
+
end
|
313
|
+
|
309
314
|
def outstanding_balance?
|
310
315
|
outstanding_balance != 0
|
311
316
|
end
|
@@ -351,6 +356,8 @@ module Spree
|
|
351
356
|
|
352
357
|
deliver_order_confirmation_email unless confirmation_delivered?
|
353
358
|
|
359
|
+
deliver_store_owner_order_notification_email if deliver_store_owner_order_notification_email?
|
360
|
+
|
354
361
|
consider_risk
|
355
362
|
end
|
356
363
|
|
@@ -641,6 +648,13 @@ module Spree
|
|
641
648
|
sum(:amount)
|
642
649
|
end
|
643
650
|
|
651
|
+
def has_free_shipping?
|
652
|
+
promotions.
|
653
|
+
joins(:promotion_actions).
|
654
|
+
where(spree_promotion_actions: { type: 'Spree::Promotion::Actions::FreeShipping' }).
|
655
|
+
exists?
|
656
|
+
end
|
657
|
+
|
644
658
|
private
|
645
659
|
|
646
660
|
def link_by_email
|
@@ -706,5 +720,17 @@ module Spree
|
|
706
720
|
def credit_card_nil_payment?(attributes)
|
707
721
|
payments.store_credits.present? && attributes[:amount].to_f.zero?
|
708
722
|
end
|
723
|
+
|
724
|
+
# Returns true if:
|
725
|
+
# 1. an email address is set for new order notifications AND
|
726
|
+
# 2. no notification for this order has been sent yet.
|
727
|
+
def deliver_store_owner_order_notification_email?
|
728
|
+
store.new_order_notifications_email.present? && !store_owner_notification_delivered?
|
729
|
+
end
|
730
|
+
|
731
|
+
def deliver_store_owner_order_notification_email
|
732
|
+
OrderMailer.store_owner_notification_email(id).deliver_later
|
733
|
+
update_column(:store_owner_notification_delivered, true)
|
734
|
+
end
|
709
735
|
end
|
710
736
|
end
|
@@ -32,7 +32,7 @@ module Spree
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def pending_payments
|
35
|
-
payments.
|
35
|
+
payments.pending
|
36
36
|
end
|
37
37
|
|
38
38
|
def unprocessed_payments
|
@@ -52,7 +52,7 @@ module Spree
|
|
52
52
|
|
53
53
|
payment.public_send(method)
|
54
54
|
|
55
|
-
if payment.completed? && payment_total !=
|
55
|
+
if payment.completed? && payment_total != total_without_pending_store_credits
|
56
56
|
self.payment_total += payment.amount
|
57
57
|
end
|
58
58
|
end
|
@@ -60,6 +60,14 @@ module Spree
|
|
60
60
|
result = !!Spree::Config[:allow_checkout_on_gateway_error]
|
61
61
|
errors.add(:base, e.message) && (return result)
|
62
62
|
end
|
63
|
+
|
64
|
+
# Pending store credits are not added to `self.payment_total`.
|
65
|
+
# It can cause a situation where the amount of the credit card payment reduced with store credits
|
66
|
+
# may be added twice to `self.payment_total` causing wrong `order.outstanding_balance`
|
67
|
+
# calculations and thus an incorrect payment state.
|
68
|
+
def total_without_pending_store_credits
|
69
|
+
total - payments.map { |p| p.amount if p.source.is_a?(Spree::StoreCredit) && p.pending? }.sum(&:to_f)
|
70
|
+
end
|
63
71
|
end
|
64
72
|
end
|
65
73
|
end
|
data/app/models/spree/price.rb
CHANGED
@@ -15,10 +15,16 @@ module Spree
|
|
15
15
|
less_than_or_equal_to: MAXIMUM_AMOUNT
|
16
16
|
}
|
17
17
|
|
18
|
+
validates :compare_at_amount, allow_nil: true, numericality: {
|
19
|
+
greater_than_or_equal_to: 0,
|
20
|
+
less_than_or_equal_to: MAXIMUM_AMOUNT
|
21
|
+
}
|
22
|
+
|
18
23
|
extend DisplayMoney
|
19
|
-
money_methods :amount, :price
|
24
|
+
money_methods :amount, :price, :compare_at_amount
|
25
|
+
alias display_compare_at_price display_compare_at_amount
|
20
26
|
|
21
|
-
self.whitelisted_ransackable_attributes = ['amount']
|
27
|
+
self.whitelisted_ransackable_attributes = ['amount', 'compare_at_amount']
|
22
28
|
|
23
29
|
def money
|
24
30
|
Spree::Money.new(amount || 0, currency: currency)
|
@@ -28,17 +34,35 @@ module Spree
|
|
28
34
|
self[:amount] = Spree::LocalizedNumber.parse(amount)
|
29
35
|
end
|
30
36
|
|
37
|
+
def compare_at_money
|
38
|
+
Spree::Money.new(compare_at_amount || 0, currency: currency)
|
39
|
+
end
|
40
|
+
|
41
|
+
def compare_at_amount=(compare_at_amount)
|
42
|
+
self[:compare_at_amount] = Spree::LocalizedNumber.parse(compare_at_amount)
|
43
|
+
end
|
44
|
+
|
31
45
|
alias_attribute :price, :amount
|
46
|
+
alias_attribute :compare_at_price, :compare_at_amount
|
32
47
|
|
33
48
|
def price_including_vat_for(price_options)
|
34
49
|
options = price_options.merge(tax_category: variant.tax_category)
|
35
50
|
gross_amount(price, options)
|
36
51
|
end
|
37
52
|
|
53
|
+
def compare_at_price_including_vat_for(price_options)
|
54
|
+
options = price_options.merge(tax_category: variant.tax_category)
|
55
|
+
gross_amount(compare_at_price, options)
|
56
|
+
end
|
57
|
+
|
38
58
|
def display_price_including_vat_for(price_options)
|
39
59
|
Spree::Money.new(price_including_vat_for(price_options), currency: currency)
|
40
60
|
end
|
41
61
|
|
62
|
+
def display_compare_at_price_including_vat_for(price_options)
|
63
|
+
Spree::Money.new(compare_at_price_including_vat_for(price_options), currency: currency)
|
64
|
+
end
|
65
|
+
|
42
66
|
# Remove variant default_scope `deleted_at: nil`
|
43
67
|
def variant
|
44
68
|
Spree::Variant.unscoped { super }
|
data/app/models/spree/product.rb
CHANGED
@@ -113,17 +113,17 @@ module Spree
|
|
113
113
|
|
114
114
|
self.whitelisted_ransackable_associations = %w[taxons stores variants_including_master master variants]
|
115
115
|
self.whitelisted_ransackable_attributes = %w[description name slug discontinue_on]
|
116
|
-
self.whitelisted_ransackable_scopes = %w[not_discontinued]
|
116
|
+
self.whitelisted_ransackable_scopes = %w[not_discontinued search_by_name]
|
117
117
|
|
118
118
|
[
|
119
119
|
:sku, :price, :currency, :weight, :height, :width, :depth, :is_master,
|
120
|
-
:cost_currency, :price_in, :amount_in, :cost_price
|
120
|
+
:cost_currency, :price_in, :amount_in, :cost_price, :compare_at_price
|
121
121
|
].each do |method_name|
|
122
122
|
delegate method_name, :"#{method_name}=", to: :find_or_build_master
|
123
123
|
end
|
124
124
|
|
125
125
|
delegate :display_amount, :display_price, :has_default_price?,
|
126
|
-
:images, to: :find_or_build_master
|
126
|
+
:display_compare_at_price, :images, to: :find_or_build_master
|
127
127
|
|
128
128
|
alias master_images images
|
129
129
|
|
@@ -160,10 +160,8 @@ module Spree
|
|
160
160
|
#
|
161
161
|
# @return [Spree::Variant]
|
162
162
|
def default_variant
|
163
|
-
|
164
|
-
|
165
|
-
Rails.cache.fetch("spree/default-variant/#{cache_key_with_version}/#{track_inventory}") do
|
166
|
-
if track_inventory && variants.in_stock_or_backorderable.any?
|
163
|
+
Rails.cache.fetch(default_variant_cache_key) do
|
164
|
+
if Spree::Config[:track_inventory_levels] && variants.in_stock_or_backorderable.any?
|
167
165
|
variants.in_stock_or_backorderable.first
|
168
166
|
else
|
169
167
|
has_variants? ? variants.first : master
|
@@ -252,6 +250,14 @@ module Spree
|
|
252
250
|
where conditions.inject(:or)
|
253
251
|
end
|
254
252
|
|
253
|
+
def self.search_by_name(query)
|
254
|
+
if defined?(SpreeGlobalize)
|
255
|
+
joins(:translations).order(:name).where("LOWER(#{Product::Translation.table_name}.name) LIKE LOWER(:query)", query: "%#{query}%").distinct
|
256
|
+
else
|
257
|
+
where("LOWER(#{Product.table_name}.name) LIKE LOWER(:query)", query: "%#{query}%")
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
255
261
|
# Suitable for displaying only variants that has at least one option value.
|
256
262
|
# There may be scenarios where an option type is removed and along with it
|
257
263
|
# all option values. At that point all variants associated with only those
|
@@ -344,6 +350,10 @@ module Spree
|
|
344
350
|
save
|
345
351
|
end
|
346
352
|
|
353
|
+
def default_variant_cache_key
|
354
|
+
"spree/default-variant/#{cache_key_with_version}/#{Spree::Config[:track_inventory_levels]}"
|
355
|
+
end
|
356
|
+
|
347
357
|
def ensure_master
|
348
358
|
return unless new_record?
|
349
359
|
|
@@ -28,6 +28,8 @@ module Spree
|
|
28
28
|
|
29
29
|
before_save :normalize_blank_values
|
30
30
|
|
31
|
+
before_validation :normalize_code
|
32
|
+
|
31
33
|
scope :coupons, -> { where.not(code: nil) }
|
32
34
|
scope :advertised, -> { where(advertise: true) }
|
33
35
|
scope :applied, lambda {
|
@@ -227,6 +229,10 @@ module Spree
|
|
227
229
|
end
|
228
230
|
end
|
229
231
|
|
232
|
+
def normalize_code
|
233
|
+
self.code = code.strip if code.present?
|
234
|
+
end
|
235
|
+
|
230
236
|
def match_all?
|
231
237
|
match_policy == 'all'
|
232
238
|
end
|
@@ -28,7 +28,7 @@ module Spree
|
|
28
28
|
|
29
29
|
if promotion.present?
|
30
30
|
# Order promotion has to be destroyed before line item removing
|
31
|
-
order.order_promotions.
|
31
|
+
order.order_promotions.where(promotion_id: promotion.id).destroy_all
|
32
32
|
|
33
33
|
remove_promotion_adjustments(promotion)
|
34
34
|
remove_promotion_line_items(promotion)
|
@@ -1,15 +1,16 @@
|
|
1
1
|
module Spree
|
2
2
|
module PromotionHandler
|
3
3
|
class PromotionDuplicator
|
4
|
-
def initialize(promotion)
|
4
|
+
def initialize(promotion, random_string: nil)
|
5
5
|
@promotion = promotion
|
6
|
+
@random_string = random_string || generate_random_string(4)
|
6
7
|
end
|
7
8
|
|
8
9
|
def duplicate
|
9
10
|
@new_promotion = @promotion.dup
|
10
|
-
@new_promotion.path = "#{@promotion.path}
|
11
|
+
@new_promotion.path = "#{@promotion.path}_#{@random_string}"
|
11
12
|
@new_promotion.name = "New #{@promotion.name}"
|
12
|
-
@new_promotion.code = "#{@promotion.code}
|
13
|
+
@new_promotion.code = "#{@promotion.code}_#{@random_string}"
|
13
14
|
|
14
15
|
ActiveRecord::Base.transaction do
|
15
16
|
@new_promotion.save
|
@@ -33,6 +34,11 @@ module Spree
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
37
|
+
def generate_random_string(number)
|
38
|
+
charset = Array('A'..'Z') + Array('a'..'z')
|
39
|
+
Array.new(number) { charset.sample }.join
|
40
|
+
end
|
41
|
+
|
36
42
|
def copy_actions
|
37
43
|
@promotion.promotion_actions.each do |action|
|
38
44
|
new_action = action.dup
|
@@ -60,6 +60,8 @@ module Spree
|
|
60
60
|
class_attribute :reimbursement_failure_hooks
|
61
61
|
self.reimbursement_failure_hooks = []
|
62
62
|
|
63
|
+
delegate :store, :currency, to: :order
|
64
|
+
|
63
65
|
state_machine :reimbursement_status, initial: :pending do
|
64
66
|
event :errored do
|
65
67
|
transition to: :errored, from: :pending
|
@@ -42,6 +42,8 @@ module Spree
|
|
42
42
|
scope :reverse_chronological, -> { order(Arel.sql('coalesce(spree_shipments.shipped_at, spree_shipments.created_at) desc'), id: :desc) }
|
43
43
|
scope :valid, -> { where.not(state: :canceled) }
|
44
44
|
|
45
|
+
delegate :store, :currency, to: :order
|
46
|
+
|
45
47
|
# shipment state machine (see http://github.com/pluginaweek/state_machine/tree/master for details)
|
46
48
|
state_machine initial: :pending, use_transactions: false do
|
47
49
|
event :ready do
|
@@ -104,11 +106,6 @@ module Spree
|
|
104
106
|
inventory_units.any?(&:backordered?)
|
105
107
|
end
|
106
108
|
|
107
|
-
# TODO: delegate currency to Order, order.currency is mandatory
|
108
|
-
def currency
|
109
|
-
order ? order.currency : Spree::Config[:currency]
|
110
|
-
end
|
111
|
-
|
112
109
|
# Determines the appropriate +state+ according to the following logic:
|
113
110
|
#
|
114
111
|
# pending unless order is complete and +order.payment_state+ is +paid+
|
@@ -106,8 +106,19 @@ module Spree
|
|
106
106
|
private
|
107
107
|
|
108
108
|
def create_stock_items
|
109
|
-
|
110
|
-
|
109
|
+
variants_scope = Spree::Variant
|
110
|
+
prepared_stock_items = variants_scope.ids.map do |variant_id|
|
111
|
+
Hash[
|
112
|
+
'stock_location_id', id,
|
113
|
+
'variant_id', variant_id,
|
114
|
+
'backorderable', backorderable_default,
|
115
|
+
'created_at', Time.current,
|
116
|
+
'updated_at', Time.current
|
117
|
+
]
|
118
|
+
end
|
119
|
+
if prepared_stock_items.any?
|
120
|
+
stock_items.insert_all(prepared_stock_items)
|
121
|
+
variants_scope.touch_all
|
111
122
|
end
|
112
123
|
end
|
113
124
|
|
data/app/models/spree/store.rb
CHANGED
@@ -2,12 +2,26 @@ module Spree
|
|
2
2
|
class Store < Spree::Base
|
3
3
|
has_many :orders, class_name: 'Spree::Order'
|
4
4
|
has_many :payment_methods, class_name: 'Spree::PaymentMethod'
|
5
|
+
belongs_to :default_country, class_name: 'Spree::Country'
|
5
6
|
|
6
7
|
with_options presence: true do
|
7
|
-
validates :name, :url, :mail_from_address
|
8
|
-
validates :default_currency
|
8
|
+
validates :name, :url, :mail_from_address, :default_currency, :code
|
9
9
|
end
|
10
10
|
|
11
|
+
validates :code, uniqueness: true
|
12
|
+
|
13
|
+
if !ENV['SPREE_DISABLE_DB_CONNECTION'] &&
|
14
|
+
connected? &&
|
15
|
+
table_exists? &&
|
16
|
+
connection.column_exists?(:spree_stores, :new_order_notifications_email)
|
17
|
+
validates :new_order_notifications_email, email: { allow_blank: true }
|
18
|
+
end
|
19
|
+
|
20
|
+
has_one_attached :logo
|
21
|
+
has_one_attached :mailer_logo
|
22
|
+
|
23
|
+
validates :mailer_logo, content_type: ['image/png', 'image/jpg', 'image/jpeg']
|
24
|
+
|
11
25
|
before_save :ensure_default_exists_and_is_unique
|
12
26
|
before_destroy :validate_not_default
|
13
27
|
|
@@ -26,6 +40,12 @@ module Spree
|
|
26
40
|
end
|
27
41
|
end
|
28
42
|
|
43
|
+
def supported_currencies_list
|
44
|
+
(read_attribute(:supported_currencies).to_s.split(',') << default_currency).map(&:to_s).map do |code|
|
45
|
+
::Money::Currency.find(code.strip)
|
46
|
+
end.uniq.compact
|
47
|
+
end
|
48
|
+
|
29
49
|
private
|
30
50
|
|
31
51
|
def ensure_default_exists_and_is_unique
|
data/app/models/spree/variant.rb
CHANGED
@@ -103,10 +103,19 @@ module Spree
|
|
103
103
|
|
104
104
|
self.whitelisted_ransackable_associations = %w[option_values product prices default_price]
|
105
105
|
self.whitelisted_ransackable_attributes = %w[weight sku]
|
106
|
-
self.whitelisted_ransackable_scopes = %i(product_name_or_sku_cont)
|
106
|
+
self.whitelisted_ransackable_scopes = %i(product_name_or_sku_cont search_by_product_name_or_sku)
|
107
107
|
|
108
108
|
def self.product_name_or_sku_cont(query)
|
109
|
-
joins(:product).where("#{Product.table_name}.name LIKE :query OR sku LIKE :query", query: "%#{query}%")
|
109
|
+
joins(:product).where("LOWER(#{Product.table_name}.name) LIKE LOWER(:query) OR LOWER(sku) LIKE LOWER(:query)", query: "%#{query}%")
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.search_by_product_name_or_sku(query)
|
113
|
+
if defined?(SpreeGlobalize)
|
114
|
+
joins(product: :translations).where("LOWER(#{Product::Translation.table_name}.name) LIKE LOWER(:query) OR LOWER(sku) LIKE LOWER(:query)",
|
115
|
+
query: "%#{query}%")
|
116
|
+
else
|
117
|
+
product_name_or_sku_cont(query)
|
118
|
+
end
|
110
119
|
end
|
111
120
|
|
112
121
|
def available?
|
@@ -223,6 +232,10 @@ module Spree
|
|
223
232
|
end.sum
|
224
233
|
end
|
225
234
|
|
235
|
+
def compare_at_price
|
236
|
+
price_in(cost_currency).try(:compare_at_amount)
|
237
|
+
end
|
238
|
+
|
226
239
|
def name_and_sku
|
227
240
|
"#{name} - #{sku}"
|
228
241
|
end
|
@@ -232,7 +245,11 @@ module Spree
|
|
232
245
|
end
|
233
246
|
|
234
247
|
def in_stock?
|
235
|
-
|
248
|
+
# Issue 10280
|
249
|
+
# Check if model responds to cache version and fall back to updated_at for older rails versions
|
250
|
+
# This makes sure a version is supplied when recyclable cache keys are disabled.
|
251
|
+
version = respond_to?(:cache_version) ? cache_version : updated_at.to_i
|
252
|
+
Rails.cache.fetch(in_stock_cache_key, version: version) do
|
236
253
|
total_on_hand > 0
|
237
254
|
end
|
238
255
|
end
|