spree_core 2.2.14 → 2.3.0
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/assets/javascripts/{spree.js.coffee → spree.js.coffee.erb} +11 -2
- data/app/controllers/spree/base_controller.rb +1 -0
- data/app/helpers/spree/base_helper.rb +5 -6
- data/app/helpers/spree/orders_helper.rb +4 -0
- data/app/helpers/spree/products_helper.rb +8 -7
- data/app/mailers/spree/base_mailer.rb +2 -2
- data/app/mailers/spree/order_mailer.rb +2 -2
- data/app/mailers/spree/shipment_mailer.rb +1 -1
- data/app/mailers/spree/test_mailer.rb +1 -1
- data/app/models/spree/ability.rb +15 -16
- data/app/models/spree/address.rb +3 -6
- data/app/models/spree/adjustment.rb +2 -2
- data/app/models/spree/alert.rb +1 -1
- data/app/models/spree/app_configuration.rb +17 -20
- data/app/models/spree/asset.rb +2 -2
- data/app/models/spree/base.rb +9 -0
- data/app/models/spree/calculator.rb +1 -1
- data/app/models/spree/calculator/flat_rate.rb +1 -1
- data/app/models/spree/calculator/flexi_rate.rb +1 -1
- data/app/models/spree/calculator/price_sack.rb +1 -3
- data/app/models/spree/calculator/shipping/flat_rate.rb +1 -1
- data/app/models/spree/calculator/shipping/flexi_rate.rb +1 -1
- data/app/models/spree/calculator/shipping/per_item.rb +1 -1
- data/app/models/spree/calculator/shipping/price_sack.rb +1 -3
- data/app/models/spree/classification.rb +1 -1
- data/app/models/spree/configuration.rb +1 -1
- data/app/models/spree/country.rb +1 -1
- data/app/models/spree/credit_card.rb +8 -12
- data/app/models/spree/gateway.rb +0 -3
- data/app/models/spree/gateway/bogus.rb +2 -3
- data/app/models/spree/image.rb +3 -1
- data/app/models/spree/inventory_unit.rb +5 -6
- data/app/models/spree/item_adjustments.rb +3 -4
- data/app/models/spree/legacy_user.rb +1 -1
- data/app/models/spree/line_item.rb +6 -13
- data/app/models/spree/log_entry.rb +1 -1
- data/app/models/spree/option_type.rb +1 -1
- data/app/models/spree/option_value.rb +1 -3
- data/app/models/spree/order.rb +52 -70
- data/app/models/spree/order/checkout.rb +17 -10
- data/app/models/spree/order/currency_updater.rb +1 -1
- data/app/models/spree/order_contents.rb +7 -4
- data/app/models/spree/order_populator.rb +1 -1
- data/app/models/spree/order_updater.rb +8 -21
- data/app/models/spree/payment.rb +26 -12
- data/app/models/spree/payment/processing.rb +5 -16
- data/app/models/spree/payment_capture_event.rb +1 -1
- data/app/models/spree/payment_method.rb +2 -2
- data/app/models/spree/payment_method/check.rb +0 -2
- data/app/models/spree/preference.rb +1 -31
- data/app/models/spree/preferences/configuration.rb +2 -6
- data/app/models/spree/preferences/preferable.rb +46 -74
- data/app/models/spree/preferences/preferable_class_methods.rb +11 -46
- data/app/models/spree/preferences/scoped_store.rb +33 -0
- data/app/models/spree/preferences/store.rb +8 -7
- data/app/models/spree/price.rb +1 -3
- data/app/models/spree/product.rb +59 -87
- data/app/models/spree/product/scopes.rb +22 -13
- data/app/models/spree/product_option_type.rb +1 -1
- data/app/models/spree/product_property.rb +1 -3
- data/app/models/spree/product_scope/scopes.rb +1 -1
- data/app/models/spree/promotion.rb +4 -5
- data/app/models/spree/promotion/actions/create_adjustment.rb +11 -2
- data/app/models/spree/promotion/actions/create_item_adjustments.rb +19 -2
- data/app/models/spree/promotion/actions/create_line_items.rb +2 -12
- data/app/models/spree/promotion/rules/user.rb +5 -1
- data/app/models/spree/promotion_action.rb +1 -1
- data/app/models/spree/promotion_action_line_item.rb +1 -1
- data/app/models/spree/promotion_handler/cart.rb +2 -14
- data/app/models/spree/promotion_handler/coupon.rb +3 -13
- data/app/models/spree/promotion_rule.rb +1 -1
- data/app/models/spree/property.rb +1 -3
- data/app/models/spree/prototype.rb +1 -1
- data/app/models/spree/return_authorization.rb +4 -10
- data/app/models/spree/role.rb +1 -1
- data/app/models/spree/shipment.rb +1 -9
- data/app/models/spree/shipping_category.rb +3 -3
- data/app/models/spree/shipping_method.rb +1 -1
- data/app/models/spree/shipping_method_category.rb +2 -2
- data/app/models/spree/shipping_rate.rb +3 -3
- data/app/models/spree/state.rb +1 -1
- data/app/models/spree/state_change.rb +1 -1
- data/app/models/spree/stock/availability_validator.rb +7 -3
- data/app/models/spree/stock/package.rb +0 -23
- data/app/models/spree/stock/splitter/backordered.rb +1 -1
- data/app/models/spree/stock/splitter/shipping_category.rb +1 -1
- data/app/models/spree/stock/splitter/weight.rb +1 -1
- data/app/models/spree/stock_item.rb +7 -10
- data/app/models/spree/stock_location.rb +2 -6
- data/app/models/spree/stock_movement.rb +1 -3
- data/app/models/spree/stock_transfer.rb +1 -3
- data/app/models/spree/store.rb +33 -0
- data/app/models/spree/tax_category.rb +2 -2
- data/app/models/spree/tax_rate.rb +21 -52
- data/app/models/spree/taxon.rb +9 -8
- data/app/models/spree/taxonomy.rb +1 -1
- data/app/models/spree/tracker.rb +1 -1
- data/app/models/spree/variant.rb +13 -15
- data/app/models/spree/variant/scopes.rb +1 -1
- data/app/models/spree/zone.rb +22 -22
- data/app/models/spree/zone_member.rb +2 -2
- data/config/initializers/user_class_extensions.rb +0 -8
- data/config/locales/en.yml +7 -42
- data/db/default/spree/countries.rb +2 -3
- data/db/default/spree/stores.rb +9 -0
- data/db/migrate/20130611054351_rename_shipping_methods_zones_to_spree_shipping_methods_zones.rb +0 -5
- data/db/migrate/20130807024301_upgrade_adjustments.rb +4 -5
- data/db/migrate/20130807024302_rename_adjustment_fields.rb +5 -2
- data/db/migrate/20131118183431_add_line_item_id_to_spree_inventory_units.rb +1 -1
- data/db/migrate/20140106065820_remove_value_type_from_spree_preferences.rb +8 -0
- data/db/migrate/20140227112348_add_preference_store_to_everything.rb +8 -0
- data/db/migrate/20140309023735_migrate_old_preferences.rb +23 -0
- data/db/migrate/20140309024355_create_spree_stores.rb +25 -0
- data/db/migrate/20140309033438_create_store_from_preferences.rb +30 -0
- data/db/migrate/20140315053743_add_timestamps_to_spree_assets.rb +6 -0
- data/db/migrate/20140331100557_add_additional_store_fields.rb +8 -0
- data/db/migrate/20140410141842_add_many_missing_indexes.rb +18 -0
- data/db/migrate/20140410150358_correct_some_polymorphic_index_and_add_more_missing.rb +66 -0
- data/db/migrate/20140508151342_change_spree_price_amount_precision.rb +1 -1
- data/db/migrate/20140518174634_add_token_to_spree_orders.rb +5 -0
- data/db/migrate/20140530024945_move_order_token_from_tokenized_permission.rb +29 -0
- data/db/migrate/20140601011216_set_shipment_total_for_users_upgrading.rb +5 -3
- data/db/migrate/20140604135309_drop_credit_card_first_name_and_last_name.rb +6 -0
- data/lib/generators/spree/dummy/dummy_generator.rb +1 -0
- data/lib/generators/spree/dummy/templates/initializers/devise.rb +3 -0
- data/lib/generators/spree/dummy/templates/rails/routes.rb +0 -1
- data/lib/generators/spree/install/install_generator.rb +8 -17
- data/lib/generators/spree/install/templates/config/initializers/spree.rb +2 -2
- data/lib/spree/core.rb +13 -9
- data/lib/spree/core/calculated_adjustments.rb +1 -1
- data/lib/spree/core/controller_helpers/auth.rb +27 -18
- data/lib/spree/core/controller_helpers/common.rb +2 -2
- data/lib/spree/core/controller_helpers/order.rb +15 -24
- data/lib/spree/core/controller_helpers/store.rb +19 -0
- data/lib/spree/core/delegate_belongs_to.rb +2 -2
- data/lib/spree/core/engine.rb +0 -10
- data/lib/spree/core/importer.rb +1 -0
- data/lib/spree/core/importer/order.rb +16 -44
- data/lib/spree/core/importer/product.rb +62 -0
- data/lib/spree/core/product_filters.rb +0 -4
- data/lib/spree/core/routes.rb +4 -6
- data/lib/spree/core/validators/email.rb +23 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/money.rb +1 -169
- data/lib/spree/permitted_attributes.rb +6 -4
- data/lib/spree/testing_support/authorization_helpers.rb +23 -21
- data/lib/spree/testing_support/capybara_ext.rb +11 -21
- data/lib/spree/testing_support/common_rake.rb +3 -1
- data/lib/spree/testing_support/controller_requests.rb +0 -2
- data/lib/spree/testing_support/factories/credit_card_factory.rb +1 -1
- data/lib/spree/testing_support/factories/line_item_factory.rb +4 -1
- data/lib/spree/testing_support/factories/order_factory.rb +5 -4
- data/lib/spree/testing_support/factories/product_factory.rb +0 -4
- data/lib/spree/testing_support/factories/promotion_factory.rb +5 -7
- data/lib/spree/testing_support/factories/shipment_factory.rb +0 -1
- data/lib/spree/testing_support/factories/stock_factory.rb +2 -2
- data/lib/spree/testing_support/factories/store_factory.rb +8 -0
- data/lib/spree/testing_support/preferences.rb +3 -3
- data/lib/tasks/core.rake +2 -2
- metadata +48 -39
- data/app/models/spree/stock/order_counter.rb +0 -55
- data/app/models/spree/tokenized_permission.rb +0 -6
- data/app/views/spree/shared/_routes.html.erb +0 -13
- data/db/migrate/20140804185157_add_default_to_shipment_cost.rb +0 -10
- data/db/migrate/20141021194502_add_state_lock_version_to_order.rb +0 -5
- data/lib/spree/core/adjustment_source.rb +0 -26
- data/lib/spree/core/mail_interceptor.rb +0 -22
- data/lib/spree/core/mail_method.rb +0 -27
- data/lib/spree/core/mail_settings.rb +0 -55
- data/lib/spree/core/ransackable_attributes.rb +0 -15
- data/lib/spree/core/token_resource.rb +0 -27
@@ -3,55 +3,33 @@ module Spree::Preferences
|
|
3
3
|
|
4
4
|
def preference(name, type, *args)
|
5
5
|
options = args.extract_options!
|
6
|
-
options.assert_valid_keys(:default
|
6
|
+
options.assert_valid_keys(:default)
|
7
7
|
default = options[:default]
|
8
|
-
|
8
|
+
default = ->{ options[:default] } unless default.is_a?(Proc)
|
9
9
|
|
10
10
|
# cache_key will be nil for new objects, then if we check if there
|
11
11
|
# is a pending preference before going to default
|
12
12
|
define_method preference_getter_method(name) do
|
13
|
-
|
14
|
-
|
15
|
-
#
|
16
|
-
if preference_cache_key(name)
|
17
|
-
preference_store.get(preference_cache_key(name), default)
|
18
|
-
else
|
19
|
-
get_pending_preference(name) || default
|
13
|
+
preferences.fetch(name) do
|
14
|
+
default.call
|
20
15
|
end
|
21
16
|
end
|
22
|
-
alias_method prefers_getter_method(name), preference_getter_method(name)
|
23
17
|
|
24
18
|
define_method preference_setter_method(name) do |value|
|
25
19
|
value = convert_preference_value(value, type)
|
26
|
-
|
27
|
-
preference_store.set preference_cache_key(name), value, type
|
28
|
-
else
|
29
|
-
add_pending_preference(name, value)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
alias_method prefers_setter_method(name), preference_setter_method(name)
|
20
|
+
preferences[name] = value
|
33
21
|
|
34
|
-
|
35
|
-
|
22
|
+
# If this is an activerecord object, we need to inform
|
23
|
+
# ActiveRecord::Dirty that this value has changed, since this is an
|
24
|
+
# in-place update to the preferences hash.
|
25
|
+
preferences_will_change! if respond_to?(:preferences_will_change!)
|
36
26
|
end
|
37
27
|
|
28
|
+
define_method preference_default_getter_method(name), &default
|
29
|
+
|
38
30
|
define_method preference_type_getter_method(name) do
|
39
31
|
type
|
40
32
|
end
|
41
|
-
|
42
|
-
define_method preference_description_getter_method(name) do
|
43
|
-
description
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def remove_preference(name)
|
48
|
-
remove_method preference_getter_method(name) if method_defined? preference_getter_method(name)
|
49
|
-
remove_method preference_setter_method(name) if method_defined? preference_setter_method(name)
|
50
|
-
remove_method prefers_getter_method(name) if method_defined? prefers_getter_method(name)
|
51
|
-
remove_method prefers_setter_method(name) if method_defined? prefers_setter_method(name)
|
52
|
-
remove_method preference_default_getter_method(name) if method_defined? preference_default_getter_method(name)
|
53
|
-
remove_method preference_type_getter_method(name) if method_defined? preference_type_getter_method(name)
|
54
|
-
remove_method preference_description_getter_method(name) if method_defined? preference_description_getter_method(name)
|
55
33
|
end
|
56
34
|
|
57
35
|
def preference_getter_method(name)
|
@@ -62,14 +40,6 @@ module Spree::Preferences
|
|
62
40
|
"preferred_#{name}=".to_sym
|
63
41
|
end
|
64
42
|
|
65
|
-
def prefers_getter_method(name)
|
66
|
-
"prefers_#{name}?".to_sym
|
67
|
-
end
|
68
|
-
|
69
|
-
def prefers_setter_method(name)
|
70
|
-
"prefers_#{name}=".to_sym
|
71
|
-
end
|
72
|
-
|
73
43
|
def preference_default_getter_method(name)
|
74
44
|
"preferred_#{name}_default".to_sym
|
75
45
|
end
|
@@ -77,10 +47,5 @@ module Spree::Preferences
|
|
77
47
|
def preference_type_getter_method(name)
|
78
48
|
"preferred_#{name}_type".to_sym
|
79
49
|
end
|
80
|
-
|
81
|
-
def preference_description_getter_method(name)
|
82
|
-
"preferred_#{name}_description".to_sym
|
83
|
-
end
|
84
|
-
|
85
50
|
end
|
86
51
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Spree::Preferences
|
2
|
+
class ScopedStore
|
3
|
+
def initialize prefix, suffix=nil
|
4
|
+
@prefix = prefix
|
5
|
+
@suffix = suffix
|
6
|
+
end
|
7
|
+
|
8
|
+
def store
|
9
|
+
Spree::Preferences::Store.instance
|
10
|
+
end
|
11
|
+
|
12
|
+
def fetch key, &block
|
13
|
+
store.fetch(key_for(key), &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def []= key, value
|
17
|
+
store[key_for(key)] = value
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete key
|
21
|
+
store.delete(key_for(key))
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def key_for key
|
26
|
+
[rails_cache_id, @prefix, key, @suffix].compact.join('/')
|
27
|
+
end
|
28
|
+
|
29
|
+
def rails_cache_id
|
30
|
+
ENV['RAILS_CACHE_ID']
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -16,17 +16,18 @@ module Spree::Preferences
|
|
16
16
|
@persistence = true
|
17
17
|
end
|
18
18
|
|
19
|
-
def set(key, value
|
19
|
+
def set(key, value)
|
20
20
|
@cache.write(key, value)
|
21
|
-
persist(key, value
|
21
|
+
persist(key, value)
|
22
22
|
end
|
23
|
+
alias_method :[]=, :set
|
23
24
|
|
24
25
|
def exist?(key)
|
25
26
|
@cache.exist?(key) ||
|
26
27
|
should_persist? && Spree::Preference.where(:key => key).exists?
|
27
28
|
end
|
28
29
|
|
29
|
-
def get(key
|
30
|
+
def get(key)
|
30
31
|
# return the retrieved value, if it's in the cache
|
31
32
|
# use unless nil? incase the value is actually boolean false
|
32
33
|
#
|
@@ -44,7 +45,7 @@ module Spree::Preferences
|
|
44
45
|
val = preference.value
|
45
46
|
else
|
46
47
|
# use the fallback value
|
47
|
-
val =
|
48
|
+
val = yield
|
48
49
|
end
|
49
50
|
|
50
51
|
# Cache either the value from the db or the fallback value.
|
@@ -53,9 +54,10 @@ module Spree::Preferences
|
|
53
54
|
|
54
55
|
return val
|
55
56
|
else
|
56
|
-
|
57
|
+
yield
|
57
58
|
end
|
58
59
|
end
|
60
|
+
alias_method :fetch, :get
|
59
61
|
|
60
62
|
def delete(key)
|
61
63
|
@cache.delete(key)
|
@@ -68,12 +70,11 @@ module Spree::Preferences
|
|
68
70
|
|
69
71
|
private
|
70
72
|
|
71
|
-
def persist(cache_key, value
|
73
|
+
def persist(cache_key, value)
|
72
74
|
return unless should_persist?
|
73
75
|
|
74
76
|
preference = Spree::Preference.where(:key => cache_key).first_or_initialize
|
75
77
|
preference.value = value
|
76
|
-
preference.value_type = type
|
77
78
|
preference.save
|
78
79
|
end
|
79
80
|
|
data/app/models/spree/price.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Spree
|
2
|
-
class Price <
|
2
|
+
class Price < Spree::Base
|
3
3
|
acts_as_paranoid
|
4
4
|
belongs_to :variant, class_name: 'Spree::Variant', inverse_of: :prices, touch: true
|
5
5
|
|
@@ -11,8 +11,6 @@ module Spree
|
|
11
11
|
end
|
12
12
|
alias :display_price :display_amount
|
13
13
|
|
14
|
-
self.whitelisted_ransackable_attributes = ['amount']
|
15
|
-
|
16
14
|
def money
|
17
15
|
Spree::Money.new(amount || 0, { currency: currency })
|
18
16
|
end
|
data/app/models/spree/product.rb
CHANGED
@@ -19,11 +19,12 @@
|
|
19
19
|
#
|
20
20
|
|
21
21
|
module Spree
|
22
|
-
class Product <
|
22
|
+
class Product < Spree::Base
|
23
23
|
extend FriendlyId
|
24
24
|
friendly_id :slug_candidates, use: :slugged
|
25
25
|
|
26
26
|
acts_as_paranoid
|
27
|
+
|
27
28
|
has_many :product_option_types, dependent: :destroy, inverse_of: :product
|
28
29
|
has_many :option_types, through: :product_option_types
|
29
30
|
has_many :product_properties, dependent: :destroy, inverse_of: :product
|
@@ -39,7 +40,8 @@ module Spree
|
|
39
40
|
has_one :master,
|
40
41
|
-> { where is_master: true },
|
41
42
|
inverse_of: :product,
|
42
|
-
class_name: 'Spree::Variant'
|
43
|
+
class_name: 'Spree::Variant',
|
44
|
+
dependent: :destroy
|
43
45
|
|
44
46
|
has_many :variants,
|
45
47
|
-> { where(is_master: false).order("#{::Spree::Variant.quoted_table_name}.position ASC") },
|
@@ -63,9 +65,9 @@ module Spree
|
|
63
65
|
after_create :set_master_variant_defaults
|
64
66
|
after_create :add_properties_and_option_types_from_prototype
|
65
67
|
after_create :build_variants_from_option_values_hash, if: :option_values_hash
|
68
|
+
|
66
69
|
after_save :save_master
|
67
|
-
after_save :
|
68
|
-
after_save :reset_nested_changes
|
70
|
+
after_save :touch
|
69
71
|
after_touch :touch_taxons
|
70
72
|
|
71
73
|
delegate :images, to: :master, prefix: true
|
@@ -91,13 +93,6 @@ module Spree
|
|
91
93
|
|
92
94
|
after_initialize :ensure_master
|
93
95
|
|
94
|
-
self.whitelisted_ransackable_associations = %w[stores variants_including_master master variants]
|
95
|
-
self.whitelisted_ransackable_attributes = %w[slug]
|
96
|
-
|
97
|
-
def to_param
|
98
|
-
slug
|
99
|
-
end
|
100
|
-
|
101
96
|
# the master variant is not a member of the variants array
|
102
97
|
def has_variants?
|
103
98
|
variants.any?
|
@@ -204,10 +199,10 @@ module Spree
|
|
204
199
|
end
|
205
200
|
|
206
201
|
def total_on_hand
|
207
|
-
if
|
202
|
+
if self.variants_including_master.any? { |v| !v.should_track_inventory? }
|
208
203
|
Float::INFINITY
|
209
204
|
else
|
210
|
-
stock_items.sum(
|
205
|
+
self.stock_items.to_a.sum(&:count_on_hand)
|
211
206
|
end
|
212
207
|
end
|
213
208
|
|
@@ -220,93 +215,70 @@ module Spree
|
|
220
215
|
|
221
216
|
private
|
222
217
|
|
223
|
-
|
224
|
-
|
225
|
-
prototype.properties.each do |property|
|
226
|
-
product_properties.create(property: property)
|
227
|
-
end
|
228
|
-
self.option_types = prototype.option_types
|
218
|
+
def normalize_slug
|
219
|
+
self.slug = normalize_friendly_id(slug)
|
229
220
|
end
|
230
|
-
end
|
231
221
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
222
|
+
# Builds variants from a hash of option types & values
|
223
|
+
def build_variants_from_option_values_hash
|
224
|
+
ensure_option_types_exist_for_values_hash
|
225
|
+
values = option_values_hash.values
|
226
|
+
values = values.inject(values.shift) { |memo, value| memo.product(value).map(&:flatten) }
|
227
|
+
|
228
|
+
values.each do |ids|
|
229
|
+
variant = variants.create(
|
230
|
+
option_value_ids: ids,
|
231
|
+
price: master.price
|
232
|
+
)
|
233
|
+
end
|
234
|
+
save
|
237
235
|
end
|
238
|
-
end
|
239
236
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
variant = variants.create(
|
248
|
-
option_value_ids: ids,
|
249
|
-
price: master.price
|
250
|
-
)
|
237
|
+
def add_properties_and_option_types_from_prototype
|
238
|
+
if prototype_id && prototype = Spree::Prototype.find_by(id: prototype_id)
|
239
|
+
prototype.properties.each do |property|
|
240
|
+
product_properties.create(property: property)
|
241
|
+
end
|
242
|
+
self.option_types = prototype.option_types
|
243
|
+
end
|
251
244
|
end
|
252
|
-
save
|
253
|
-
end
|
254
|
-
|
255
|
-
def ensure_master
|
256
|
-
return unless new_record?
|
257
|
-
self.master ||= Variant.new
|
258
|
-
end
|
259
245
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
def punch_slug
|
265
|
-
update_column :slug, "#{Time.now.to_i}_#{slug}" # punch slug with date prefix to allow reuse of original
|
266
|
-
end
|
267
|
-
|
268
|
-
def anything_changed?
|
269
|
-
changed? || @nested_changes
|
270
|
-
end
|
271
|
-
|
272
|
-
def reset_nested_changes
|
273
|
-
@nested_changes = false
|
274
|
-
end
|
246
|
+
# ensures the master variant is flagged as such
|
247
|
+
def set_master_variant_defaults
|
248
|
+
master.is_master = true
|
249
|
+
end
|
275
250
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
master.save
|
281
|
-
@nested_changes = true
|
251
|
+
# there's a weird quirk with the delegate stuff that does not automatically save the delegate object
|
252
|
+
# when saving so we force a save using a hook.
|
253
|
+
def save_master
|
254
|
+
master.save if master && (master.changed? || master.new_record? || (master.default_price && (master.default_price.changed? || master.default_price.new_record?)))
|
282
255
|
end
|
283
|
-
end
|
284
256
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
257
|
+
def ensure_master
|
258
|
+
return unless new_record?
|
259
|
+
self.master ||= Variant.new
|
260
|
+
end
|
289
261
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
[:name, :sku]
|
295
|
-
]
|
296
|
-
end
|
262
|
+
# Iterate through this products taxons and taxonomies and touch their timestamps in a batch
|
263
|
+
def touch_taxons
|
264
|
+
taxons_to_touch = taxons.map(&:self_and_ancestors).flatten.uniq
|
265
|
+
Spree::Taxon.where(id: taxons_to_touch.map(&:id)).update_all(updated_at: Time.current)
|
297
266
|
|
298
|
-
|
299
|
-
|
300
|
-
|
267
|
+
taxonomy_ids_to_touch = taxons_to_touch.map(&:taxonomy_id).flatten.uniq
|
268
|
+
Spree::Taxonomy.where(id: taxonomy_ids_to_touch).update_all(updated_at: Time.current)
|
269
|
+
end
|
301
270
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
271
|
+
# Try building a slug based on the following fields in increasing order of specificity.
|
272
|
+
def slug_candidates
|
273
|
+
[
|
274
|
+
:name,
|
275
|
+
[:name, :sku]
|
276
|
+
]
|
277
|
+
end
|
306
278
|
|
307
|
-
|
308
|
-
|
309
|
-
|
279
|
+
def punch_slug
|
280
|
+
update(slug: "#{Time.now.to_i}_#{slug}") # punch slug with date prefix to allow reuse of original
|
281
|
+
end
|
310
282
|
|
311
283
|
end
|
312
284
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Spree
|
2
|
-
class Product <
|
2
|
+
class Product < Spree::Base
|
3
3
|
cattr_accessor :search_scopes do
|
4
4
|
[]
|
5
5
|
end
|
@@ -201,19 +201,28 @@ module Spree
|
|
201
201
|
group("spree_products.id").joins(:taxons).where(Taxon.arel_table[:name].eq(name))
|
202
202
|
end
|
203
203
|
|
204
|
-
def self.distinct_by_product_ids(sort_order=nil)
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
204
|
+
def self.distinct_by_product_ids(sort_order = nil)
|
205
|
+
sort_column = sort_order.split(" ").first
|
206
|
+
|
207
|
+
# Postgres will complain when using ordering by expressions not present in
|
208
|
+
# SELECT DISTINCT. e.g.
|
209
|
+
#
|
210
|
+
# PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY
|
211
|
+
# expressions must appear in select list. e.g.
|
212
|
+
#
|
213
|
+
# SELECT DISTINCT "spree_products".* FROM "spree_products" LEFT OUTER JOIN
|
214
|
+
# "spree_variants" ON "spree_variants"."product_id" = "spree_products"."id" AND "spree_variants"."is_master" = 't'
|
215
|
+
# AND "spree_variants"."deleted_at" IS NULL LEFT OUTER JOIN "spree_prices" ON
|
216
|
+
# "spree_prices"."variant_id" = "spree_variants"."id" AND "spree_prices"."currency" = 'USD'
|
217
|
+
# AND "spree_prices"."deleted_at" IS NULL WHERE "spree_products"."deleted_at" IS NULL AND ('t'='t')
|
218
|
+
# ORDER BY "spree_prices"."amount" ASC LIMIT 10 OFFSET 0
|
219
|
+
#
|
220
|
+
# Don't allow sort_column, a variable coming from params,
|
221
|
+
# to be anything but a column in the database
|
222
|
+
if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' && !column_names.include?(sort_column)
|
223
|
+
all
|
215
224
|
else
|
216
|
-
|
225
|
+
distinct
|
217
226
|
end
|
218
227
|
end
|
219
228
|
|