spree_core 4.2.0.rc2 → 4.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/spree.js +20 -0
- data/app/controllers/spree/base_controller.rb +2 -3
- data/app/controllers/spree/errors_controller.rb +11 -0
- data/app/finders/spree/addresses/find.rb +1 -12
- data/app/finders/spree/base_finder.rb +14 -0
- data/app/finders/spree/countries/find.rb +11 -3
- data/app/finders/spree/credit_cards/find.rb +2 -2
- data/app/finders/spree/orders/find_current.rb +2 -2
- data/app/finders/spree/products/find.rb +14 -3
- data/app/helpers/spree/base_helper.rb +3 -8
- data/app/helpers/spree/currency_helper.rb +34 -0
- data/app/helpers/spree/locale_helper.rb +31 -0
- data/app/helpers/spree/products_helper.rb +37 -12
- data/app/mailers/spree/base_mailer.rb +4 -4
- data/app/mailers/spree/order_mailer.rb +3 -3
- data/app/mailers/spree/reimbursement_mailer.rb +1 -1
- data/app/mailers/spree/shipment_mailer.rb +1 -1
- data/app/models/concerns/spree/default_price.rb +1 -5
- data/app/models/concerns/spree/product_scopes.rb +1 -1
- data/app/models/concerns/spree/user_methods.rb +2 -2
- data/app/models/concerns/spree/user_payment_source.rb +1 -1
- data/app/models/spree/ability.rb +45 -34
- data/app/models/spree/address.rb +4 -0
- data/app/models/spree/app_configuration.rb +2 -2
- data/app/models/spree/app_dependencies.rb +6 -2
- data/app/models/spree/base.rb +5 -0
- data/app/models/spree/credit_card.rb +4 -0
- data/app/models/spree/fulfilment_changer.rb +58 -16
- data/app/models/spree/image.rb +14 -14
- data/app/models/spree/inventory_unit.rb +2 -7
- data/app/models/spree/line_item.rb +7 -15
- data/app/models/spree/order.rb +1 -0
- data/app/models/spree/payment.rb +18 -4
- data/app/models/spree/payment/processing.rb +2 -2
- data/app/models/spree/payment_method.rb +3 -3
- data/app/models/spree/price.rb +2 -7
- data/app/models/spree/product.rb +41 -17
- data/app/models/spree/promotion/rules/option_value.rb +1 -1
- data/app/models/spree/promotion/rules/product.rb +2 -1
- data/app/models/spree/promotion/rules/user.rb +2 -1
- data/app/models/spree/refund.rb +2 -2
- data/app/models/spree/return_item/eligibility_validator/default.rb +0 -2
- data/app/models/spree/return_item/eligibility_validator/{r_m_a_required.rb → rma_required.rb} +0 -0
- data/app/models/spree/shipment.rb +1 -1
- data/app/models/spree/shipping_method.rb +1 -5
- data/app/models/spree/shipping_rate.rb +2 -11
- data/app/models/spree/stock/availability_validator.rb +3 -4
- data/app/models/spree/stock_item.rb +1 -5
- data/app/models/spree/store.rb +55 -2
- data/app/models/spree/store_credit.rb +1 -1
- data/app/models/spree/variant.rb +9 -16
- data/app/models/spree/zone.rb +13 -4
- data/app/paginators/spree/shared/paginate.rb +8 -1
- data/app/presenters/spree/variant_presenter.rb +2 -5
- data/app/services/spree/account/addresses/create.rb +6 -1
- data/app/services/spree/account/addresses/{base.rb → helper.rb} +1 -3
- data/app/services/spree/account/addresses/update.rb +6 -1
- data/app/services/spree/build_localized_redirect_url.rb +101 -0
- data/app/services/spree/cart/estimate_shipping_rates.rb +1 -1
- data/app/services/spree/compare_line_items.rb +4 -2
- data/app/sorters/spree/base_sorter.rb +35 -0
- data/app/sorters/spree/orders/sort.rb +1 -37
- data/app/sorters/spree/products/sort.rb +9 -32
- data/app/validators/email_validator.rb +1 -1
- data/app/views/spree/errors/forbidden.html.erb +0 -0
- data/app/views/spree/errors/unauthorized.html.erb +0 -0
- data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +13 -2
- data/app/views/spree/shared/_purchased_items_table.html.erb +15 -6
- data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +2 -2
- data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +2 -2
- data/config/initializers/inflections.rb +3 -0
- data/config/initializers/rails61_fixes.rb +3 -0
- data/config/locales/en.yml +31 -60
- data/config/routes.rb +2 -1
- data/db/default/spree/stores.rb +1 -0
- data/db/default/spree/zones.rb +4 -1
- data/db/migrate/20130326175857_add_stock_location_to_rma.rb +1 -1
- data/db/migrate/20191017121054_add_supported_currencies_to_store.rb +1 -0
- data/db/migrate/20201012091259_add_filterable_column_to_spree_option_types.rb +6 -2
- data/db/migrate/20201127084048_add_default_country_kind_to_spree_zones.rb +5 -0
- data/db/migrate/20210112193440_remove_contact_email_from_spree_stores.rb +5 -0
- data/db/migrate/20210114182625_create_spree_payment_methods_stores.rb +10 -0
- data/db/migrate/20210114220232_migrate_data_payment_methods_stores.rb +15 -0
- data/db/migrate/20210117112551_remove_store_id_from_spree_payment_methods.rb +5 -0
- data/db/migrate/20210120142527_ensure_default_locale_in_spree_stores.rb +5 -0
- data/db/migrate/20210205211040_add_supported_locales_to_spree_stores.rb +11 -0
- data/db/migrate/20210215202602_migrate_spree_i18n_globalize_config.rb +22 -0
- data/lib/generators/spree/install/install_generator.rb +9 -6
- data/lib/spree/core.rb +2 -1
- data/lib/spree/core/controller_helpers/auth.rb +3 -1
- data/lib/spree/core/controller_helpers/common.rb +6 -8
- data/lib/spree/core/controller_helpers/currency.rb +54 -0
- data/lib/spree/core/controller_helpers/locale.rb +58 -0
- data/lib/spree/core/controller_helpers/search.rb +1 -1
- data/lib/spree/core/controller_helpers/store.rb +4 -16
- data/lib/spree/core/product_filters.rb +3 -3
- data/lib/spree/core/version.rb +3 -1
- data/lib/spree/i18n.rb +17 -19
- data/lib/spree/permitted_attributes.rb +2 -2
- data/lib/spree/service_module.rb +8 -4
- data/lib/spree/testing_support/capybara_config.rb +1 -1
- data/lib/spree/testing_support/common_rake.rb +1 -1
- data/lib/spree/testing_support/controller_requests.rb +10 -10
- data/lib/spree/testing_support/factories/shipment_factory.rb +7 -9
- data/lib/spree/testing_support/factories/stock_location_factory.rb +2 -2
- data/lib/spree/testing_support/factories/store_factory.rb +1 -0
- data/lib/spree/testing_support/factories/zone_factory.rb +16 -13
- data/lib/spree/testing_support/flatpickr_capybara.rb +101 -0
- data/lib/spree/testing_support/locale_helpers.rb +78 -0
- data/lib/spree/testing_support/next_instance_of.rb +38 -0
- data/lib/spree/testing_support/order_walkthrough.rb +8 -3
- data/lib/spree/testing_support/rspec_retry_config.rb +10 -0
- data/spree_core.gemspec +5 -4
- metadata +71 -26
- data/lib/generators/spree/install/templates/config/initializers/spree_storefront.rb +0 -1
- data/lib/generators/spree/install/templates/config/spree_storefront.yml +0 -67
- data/lib/spree/core/controller_helpers/currency_helpers.rb +0 -15
- data/lib/spree/i18n/base.rb +0 -17
- data/lib/spree/i18n/initializer.rb +0 -1
data/app/models/spree/order.rb
CHANGED
@@ -157,6 +157,7 @@ module Spree
|
|
157
157
|
scope :completed_between, ->(start_date, end_date) { where(completed_at: start_date..end_date) }
|
158
158
|
scope :complete, -> { where.not(completed_at: nil) }
|
159
159
|
scope :incomplete, -> { where(completed_at: nil) }
|
160
|
+
scope :not_canceled, -> { where.not(state: 'canceled') }
|
160
161
|
|
161
162
|
# shows completed orders first, by their completed_at date, then uncompleted orders by their created_at
|
162
163
|
scope :reverse_chronological, -> { order(Arel.sql('spree_orders.completed_at IS NULL'), completed_at: :desc, created_at: :desc) }
|
data/app/models/spree/payment.rb
CHANGED
@@ -14,7 +14,7 @@ module Spree
|
|
14
14
|
|
15
15
|
with_options inverse_of: :payments do
|
16
16
|
belongs_to :order, class_name: 'Spree::Order', touch: true
|
17
|
-
belongs_to :payment_method, class_name: 'Spree::PaymentMethod'
|
17
|
+
belongs_to :payment_method, -> { with_deleted }, class_name: 'Spree::PaymentMethod'
|
18
18
|
end
|
19
19
|
belongs_to :source, polymorphic: true
|
20
20
|
|
@@ -195,14 +195,28 @@ module Spree
|
|
195
195
|
|
196
196
|
def validate_source
|
197
197
|
if source && !source.valid?
|
198
|
-
|
199
|
-
|
200
|
-
|
198
|
+
if Rails::VERSION::STRING >= '6.1'
|
199
|
+
source.errors.map { |error| { field: error.attribute, message: error&.message } }.each do |err|
|
200
|
+
next if err[:field].blank? || err[:message].blank?
|
201
|
+
|
202
|
+
add_source_error(err[:field], err[:message])
|
203
|
+
end
|
204
|
+
else
|
205
|
+
source.errors.messages.each do |field, error|
|
206
|
+
next if field.blank? || error.empty?
|
207
|
+
|
208
|
+
add_source_error(field, error.first)
|
209
|
+
end
|
201
210
|
end
|
202
211
|
end
|
203
212
|
!errors.present?
|
204
213
|
end
|
205
214
|
|
215
|
+
def add_source_error(field, message)
|
216
|
+
field_name = I18n.t("activerecord.attributes.#{source.class.to_s.underscore}.#{field}")
|
217
|
+
errors.add(Spree.t(source.class.to_s.demodulize.underscore), "#{field_name} #{message}")
|
218
|
+
end
|
219
|
+
|
206
220
|
def profiles_supported?
|
207
221
|
payment_method.respond_to?(:payment_profiles_supported?) && payment_method.payment_profiles_supported?
|
208
222
|
end
|
@@ -163,8 +163,8 @@ module Spree
|
|
163
163
|
else
|
164
164
|
error.to_s
|
165
165
|
end
|
166
|
-
logger.error(Spree.t(:gateway_error))
|
167
|
-
logger.error(" #{error.to_yaml}")
|
166
|
+
Rails.logger.error(Spree.t(:gateway_error))
|
167
|
+
Rails.logger.error(" #{error.to_yaml}")
|
168
168
|
raise Core::GatewayError, text
|
169
169
|
end
|
170
170
|
|
@@ -12,7 +12,7 @@ module Spree
|
|
12
12
|
|
13
13
|
validates :name, presence: true
|
14
14
|
|
15
|
-
|
15
|
+
has_and_belongs_to_many :stores
|
16
16
|
|
17
17
|
with_options dependent: :restrict_with_error do
|
18
18
|
has_many :payments, class_name: 'Spree::Payment', inverse_of: :payment_method
|
@@ -79,9 +79,9 @@ module Spree
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def available_for_store?(store)
|
82
|
-
return true if store.blank?
|
82
|
+
return true if store.blank?
|
83
83
|
|
84
|
-
|
84
|
+
store_ids.include?(store.id)
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
data/app/models/spree/price.rb
CHANGED
@@ -6,7 +6,7 @@ module Spree
|
|
6
6
|
|
7
7
|
MAXIMUM_AMOUNT = BigDecimal('99_999_999.99')
|
8
8
|
|
9
|
-
belongs_to :variant, class_name: 'Spree::Variant', inverse_of: :prices, touch: true
|
9
|
+
belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant', inverse_of: :prices, touch: true
|
10
10
|
|
11
11
|
before_validation :ensure_currency
|
12
12
|
|
@@ -27,7 +27,7 @@ module Spree
|
|
27
27
|
self.whitelisted_ransackable_attributes = ['amount', 'compare_at_amount']
|
28
28
|
|
29
29
|
def money
|
30
|
-
Spree::Money.new(amount || 0, currency: currency)
|
30
|
+
Spree::Money.new(amount || 0, currency: currency.upcase)
|
31
31
|
end
|
32
32
|
|
33
33
|
def amount=(amount)
|
@@ -63,11 +63,6 @@ module Spree
|
|
63
63
|
Spree::Money.new(compare_at_price_including_vat_for(price_options), currency: currency)
|
64
64
|
end
|
65
65
|
|
66
|
-
# Remove variant default_scope `deleted_at: nil`
|
67
|
-
def variant
|
68
|
-
Spree::Variant.unscoped { super }
|
69
|
-
end
|
70
|
-
|
71
66
|
private
|
72
67
|
|
73
68
|
def ensure_currency
|
data/app/models/spree/product.rb
CHANGED
@@ -90,6 +90,10 @@ module Spree
|
|
90
90
|
after_save :reset_nested_changes
|
91
91
|
after_touch :touch_taxons
|
92
92
|
|
93
|
+
# reset cache on save inside trasaction and transaction commit
|
94
|
+
after_save :reset_memoized_data
|
95
|
+
after_commit :reset_memoized_data
|
96
|
+
|
93
97
|
before_validation :normalize_slug, on: :update
|
94
98
|
before_validation :validate_master
|
95
99
|
|
@@ -127,6 +131,13 @@ module Spree
|
|
127
131
|
|
128
132
|
alias master_images images
|
129
133
|
|
134
|
+
def reload
|
135
|
+
%w(total_on_hand taxonomy_ids taxon_and_ancestors category category default_variant_id tax_category default_variant).each do |v|
|
136
|
+
instance_variable_set(:"@#{v}", nil)
|
137
|
+
end
|
138
|
+
super
|
139
|
+
end
|
140
|
+
|
130
141
|
# Cant use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
|
131
142
|
def purchasable?
|
132
143
|
variants_including_master.any?(&:purchasable?)
|
@@ -160,7 +171,7 @@ module Spree
|
|
160
171
|
#
|
161
172
|
# @return [Spree::Variant]
|
162
173
|
def default_variant
|
163
|
-
Rails.cache.fetch(default_variant_cache_key) do
|
174
|
+
@default_variant ||= Rails.cache.fetch(default_variant_cache_key) do
|
164
175
|
if Spree::Config[:track_inventory_levels] && variants.in_stock_or_backorderable.any?
|
165
176
|
variants.in_stock_or_backorderable.first
|
166
177
|
else
|
@@ -172,11 +183,11 @@ module Spree
|
|
172
183
|
# Returns default Variant ID for Product
|
173
184
|
# @return [Integer]
|
174
185
|
def default_variant_id
|
175
|
-
default_variant.id
|
186
|
+
@default_variant_id ||= default_variant.id
|
176
187
|
end
|
177
188
|
|
178
189
|
def tax_category
|
179
|
-
super || TaxCategory.find_by(is_default: true)
|
190
|
+
@tax_category ||= super || TaxCategory.find_by(is_default: true)
|
180
191
|
end
|
181
192
|
|
182
193
|
# Adding properties and option types on creation based on a chosen prototype
|
@@ -288,11 +299,11 @@ module Spree
|
|
288
299
|
end
|
289
300
|
|
290
301
|
def total_on_hand
|
291
|
-
if any_variants_not_track_inventory?
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
302
|
+
@total_on_hand ||= if any_variants_not_track_inventory?
|
303
|
+
Float::INFINITY
|
304
|
+
else
|
305
|
+
stock_items.sum(:count_on_hand)
|
306
|
+
end
|
296
307
|
end
|
297
308
|
|
298
309
|
# Master variant may be deleted (i.e. when the product is deleted)
|
@@ -303,14 +314,11 @@ module Spree
|
|
303
314
|
end
|
304
315
|
|
305
316
|
def brand
|
306
|
-
taxons.joins(:taxonomy).find_by(spree_taxonomies: { name: Spree.t(:taxonomy_brands_name) })
|
317
|
+
@brand ||= taxons.joins(:taxonomy).find_by(spree_taxonomies: { name: Spree.t(:taxonomy_brands_name) })
|
307
318
|
end
|
308
319
|
|
309
320
|
def category
|
310
|
-
taxons.joins(:taxonomy).
|
311
|
-
where(spree_taxonomies: { name: Spree.t(:taxonomy_categories_name) }).
|
312
|
-
order(depth: :desc).
|
313
|
-
first
|
321
|
+
@category ||= taxons.joins(:taxonomy).order(depth: :desc).find_by(spree_taxonomies: { name: Spree.t(:taxonomy_categories_name) })
|
314
322
|
end
|
315
323
|
|
316
324
|
private
|
@@ -411,8 +419,18 @@ module Spree
|
|
411
419
|
# We call master.default_price here to ensure price is initialized.
|
412
420
|
# Required to avoid Variant#check_price validation failing on create.
|
413
421
|
unless master.default_price && master.valid?
|
414
|
-
|
415
|
-
errors.
|
422
|
+
if Rails::VERSION::STRING >= '6.1'
|
423
|
+
master.errors.map { |error| { field: error.attribute, message: error&.message } }.each do |err|
|
424
|
+
next if err[:field].blank? || err[:message].blank?
|
425
|
+
|
426
|
+
errors.add(err[:field], err[:message])
|
427
|
+
end
|
428
|
+
else
|
429
|
+
master.errors.messages.each do |field, error|
|
430
|
+
next if field.blank? || error.empty?
|
431
|
+
|
432
|
+
errors.add(field, error.first)
|
433
|
+
end
|
416
434
|
end
|
417
435
|
end
|
418
436
|
end
|
@@ -430,12 +448,12 @@ module Spree
|
|
430
448
|
end
|
431
449
|
|
432
450
|
def taxon_and_ancestors
|
433
|
-
taxons.map(&:self_and_ancestors).flatten.uniq
|
451
|
+
@taxon_and_ancestors ||= taxons.map(&:self_and_ancestors).flatten.uniq
|
434
452
|
end
|
435
453
|
|
436
454
|
# Get the taxonomy ids of all taxons assigned to this product and their ancestors.
|
437
455
|
def taxonomy_ids
|
438
|
-
taxon_and_ancestors.map(&:taxonomy_id).flatten.uniq
|
456
|
+
@taxonomy_ids ||= taxon_and_ancestors.map(&:taxonomy_id).flatten.uniq
|
439
457
|
end
|
440
458
|
|
441
459
|
# Iterate through this products taxons and taxonomies and touch their timestamps in a batch
|
@@ -461,5 +479,11 @@ module Spree
|
|
461
479
|
errors.add(:discontinue_on, :invalid_date_range)
|
462
480
|
end
|
463
481
|
end
|
482
|
+
|
483
|
+
def reset_memoized_data
|
484
|
+
%w(total_on_hand taxonomy_ids taxon_and_ancestors category default_variant_id tax_category default_variant).each do |v|
|
485
|
+
instance_variable_set(:"@#{v}", nil)
|
486
|
+
end
|
487
|
+
end
|
464
488
|
end
|
465
489
|
end
|
@@ -31,7 +31,7 @@ module Spree
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def actionable?(line_item)
|
34
|
-
product_id = line_item.
|
34
|
+
product_id = line_item.product_id
|
35
35
|
option_values_ids = line_item.variant.option_value_ids
|
36
36
|
eligible_product_ids = preferred_eligible_values.keys
|
37
37
|
eligible_value_ids = preferred_eligible_values[product_id]
|
data/app/models/spree/refund.rb
CHANGED
@@ -61,14 +61,14 @@ module Spree
|
|
61
61
|
end
|
62
62
|
|
63
63
|
unless response.success?
|
64
|
-
logger.error(Spree.t(:gateway_error) + " #{response.to_yaml}")
|
64
|
+
Rails.logger.error(Spree.t(:gateway_error) + " #{response.to_yaml}")
|
65
65
|
text = response.params['message'] || response.params['response_reason_text'] || response.message
|
66
66
|
raise Core::GatewayError, text
|
67
67
|
end
|
68
68
|
|
69
69
|
response
|
70
70
|
rescue ActiveMerchant::ConnectionError => e
|
71
|
-
logger.error(Spree.t(:gateway_error) + " #{e.inspect}")
|
71
|
+
Rails.logger.error(Spree.t(:gateway_error) + " #{e.inspect}")
|
72
72
|
raise Core::GatewayError, Spree.t(:unable_to_connect_to_gateway)
|
73
73
|
end
|
74
74
|
|
data/app/models/spree/return_item/eligibility_validator/{r_m_a_required.rb → rma_required.rb}
RENAMED
File without changes
|
@@ -19,7 +19,7 @@ module Spree
|
|
19
19
|
foreign_key: 'shipping_method_id'
|
20
20
|
has_many :zones, through: :shipping_method_zones, class_name: 'Spree::Zone'
|
21
21
|
|
22
|
-
belongs_to :tax_category, class_name: 'Spree::TaxCategory', optional: true
|
22
|
+
belongs_to :tax_category, -> { with_deleted }, class_name: 'Spree::TaxCategory', optional: true
|
23
23
|
|
24
24
|
validates :name, :display_on, presence: true
|
25
25
|
|
@@ -44,10 +44,6 @@ module Spree
|
|
44
44
|
select { |c| c.to_s.constantize < Spree::ShippingCalculator }
|
45
45
|
end
|
46
46
|
|
47
|
-
def tax_category
|
48
|
-
Spree::TaxCategory.unscoped { super }
|
49
|
-
end
|
50
|
-
|
51
47
|
def available_to_display?(display_filter)
|
52
48
|
(frontend? && display_filter == DISPLAY_ON_FRONT_END) ||
|
53
49
|
(backend? && display_filter == DISPLAY_ON_BACK_END)
|
@@ -1,9 +1,8 @@
|
|
1
1
|
module Spree
|
2
2
|
class ShippingRate < Spree::Base
|
3
3
|
belongs_to :shipment, class_name: 'Spree::Shipment'
|
4
|
-
belongs_to :tax_rate, class_name: 'Spree::TaxRate'
|
5
|
-
belongs_to :shipping_method, class_name: 'Spree::ShippingMethod', inverse_of: :shipping_rates
|
6
|
-
|
4
|
+
belongs_to :tax_rate, -> { with_deleted }, class_name: 'Spree::TaxRate'
|
5
|
+
belongs_to :shipping_method, -> { with_deleted }, class_name: 'Spree::ShippingMethod', inverse_of: :shipping_rates
|
7
6
|
extend Spree::DisplayMoney
|
8
7
|
|
9
8
|
money_methods :base_price, :final_price, :tax_amount
|
@@ -32,14 +31,6 @@ module Spree
|
|
32
31
|
@tax_amount ||= tax_rate&.calculator&.compute_shipping_rate(self) || BigDecimal(0)
|
33
32
|
end
|
34
33
|
|
35
|
-
def shipping_method
|
36
|
-
Spree::ShippingMethod.unscoped { super }
|
37
|
-
end
|
38
|
-
|
39
|
-
def tax_rate
|
40
|
-
Spree::TaxRate.unscoped { super }
|
41
|
-
end
|
42
|
-
|
43
34
|
# returns base price - any available discounts for this Shipment
|
44
35
|
# useful when you want to present a list of available shipping rates
|
45
36
|
def final_price
|
@@ -14,10 +14,9 @@ module Spree
|
|
14
14
|
display_name = variant.name.to_s
|
15
15
|
display_name += " (#{variant.options_text})" unless variant.options_text.blank?
|
16
16
|
|
17
|
-
line_item.errors
|
18
|
-
|
19
|
-
|
20
|
-
)
|
17
|
+
line_item.errors.add(:quantity,
|
18
|
+
:selected_quantity_not_available,
|
19
|
+
message: Spree.t(:selected_quantity_not_available, item: display_name.inspect))
|
21
20
|
end
|
22
21
|
|
23
22
|
private
|
@@ -4,7 +4,7 @@ module Spree
|
|
4
4
|
|
5
5
|
with_options inverse_of: :stock_items do
|
6
6
|
belongs_to :stock_location, class_name: 'Spree::StockLocation'
|
7
|
-
belongs_to :variant, class_name: 'Spree::Variant'
|
7
|
+
belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant'
|
8
8
|
end
|
9
9
|
has_many :stock_movements, inverse_of: :stock_item
|
10
10
|
|
@@ -56,10 +56,6 @@ module Spree
|
|
56
56
|
in_stock? || backorderable?
|
57
57
|
end
|
58
58
|
|
59
|
-
def variant
|
60
|
-
Spree::Variant.unscoped { super }
|
61
|
-
end
|
62
|
-
|
63
59
|
def reduce_count_on_hand_to_zero
|
64
60
|
set_count_on_hand(0) if count_on_hand > 0
|
65
61
|
end
|
data/app/models/spree/store.rb
CHANGED
@@ -24,12 +24,15 @@ module Spree
|
|
24
24
|
validates :mailer_logo, content_type: ['image/png', 'image/jpg', 'image/jpeg']
|
25
25
|
|
26
26
|
before_save :ensure_default_exists_and_is_unique
|
27
|
+
before_save :ensure_supported_currencies, :ensure_supported_locales
|
27
28
|
before_destroy :validate_not_default
|
28
29
|
|
29
30
|
scope :by_url, ->(url) { where('url like ?', "%#{url}%") }
|
30
31
|
|
31
32
|
after_commit :clear_cache
|
32
33
|
|
34
|
+
alias_attribute :contact_email, :customer_support_email
|
35
|
+
|
33
36
|
def self.current(domain = nil)
|
34
37
|
current_store = domain ? Store.by_url(domain).first : nil
|
35
38
|
current_store || Store.default
|
@@ -41,14 +44,47 @@ module Spree
|
|
41
44
|
end
|
42
45
|
end
|
43
46
|
|
47
|
+
def self.available_locales
|
48
|
+
Rails.cache.fetch('stores_available_locales') do
|
49
|
+
Spree::Store.all.map(&:supported_locales_list).flatten.uniq
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
44
53
|
def supported_currencies_list
|
45
|
-
(read_attribute(:supported_currencies).to_s.split(',') << default_currency).map(&:to_s).map do |code|
|
54
|
+
@supported_currencies_list ||= (read_attribute(:supported_currencies).to_s.split(',') << default_currency).sort.map(&:to_s).map do |code|
|
46
55
|
::Money::Currency.find(code.strip)
|
47
56
|
end.uniq.compact
|
48
57
|
end
|
49
58
|
|
59
|
+
def supported_locales_list
|
60
|
+
# TODO: add support of multiple supported languages to a single Store
|
61
|
+
@supported_locales_list ||= (read_attribute(:supported_locales).to_s.split(',') << default_locale).compact.uniq.sort
|
62
|
+
end
|
63
|
+
|
50
64
|
def unique_name
|
51
|
-
"#{name} (#{code})"
|
65
|
+
@unique_name ||= "#{name} (#{code})"
|
66
|
+
end
|
67
|
+
|
68
|
+
def formatted_url
|
69
|
+
return if url.blank?
|
70
|
+
|
71
|
+
@formatted_url ||= if url.match(/http:\/\/|https:\/\//)
|
72
|
+
url
|
73
|
+
else
|
74
|
+
Rails.env.development? ? "http://#{url}" : "https://#{url}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def countries_available_for_checkout
|
79
|
+
@countries_available_for_checkout ||= checkout_zone_or_default.try(:country_list) || Spree::Country.all
|
80
|
+
end
|
81
|
+
|
82
|
+
def states_available_for_checkout(country)
|
83
|
+
checkout_zone_or_default.try(:state_list_for, country) || country.states
|
84
|
+
end
|
85
|
+
|
86
|
+
def checkout_zone_or_default
|
87
|
+
@checkout_zone_or_default ||= checkout_zone || Spree::Zone.default_checkout_zone
|
52
88
|
end
|
53
89
|
|
54
90
|
private
|
@@ -61,6 +97,22 @@ module Spree
|
|
61
97
|
end
|
62
98
|
end
|
63
99
|
|
100
|
+
def ensure_supported_locales
|
101
|
+
return unless attributes.keys.include?('supported_locales')
|
102
|
+
return if supported_locales.present?
|
103
|
+
return if default_locale.blank?
|
104
|
+
|
105
|
+
self.supported_locales = default_locale
|
106
|
+
end
|
107
|
+
|
108
|
+
def ensure_supported_currencies
|
109
|
+
return unless attributes.keys.include?('supported_currencies')
|
110
|
+
return if supported_currencies.present?
|
111
|
+
return if default_currency.blank?
|
112
|
+
|
113
|
+
self.supported_currencies = default_currency
|
114
|
+
end
|
115
|
+
|
64
116
|
def validate_not_default
|
65
117
|
if default
|
66
118
|
errors.add(:base, :cannot_destroy_default_store)
|
@@ -70,6 +122,7 @@ module Spree
|
|
70
122
|
|
71
123
|
def clear_cache
|
72
124
|
Rails.cache.delete('default_store')
|
125
|
+
Rails.cache.delete('stores_available_locales')
|
73
126
|
end
|
74
127
|
end
|
75
128
|
end
|