solidus_core 2.9.5 → 2.10.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of solidus_core might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/app/helpers/spree/base_helper.rb +4 -4
- data/app/helpers/spree/products_helper.rb +2 -1
- data/app/jobs/spree/promotion_code_batch_job.rb +2 -2
- data/app/models/concerns/spree/user_address_book.rb +2 -2
- data/app/models/concerns/spree/user_methods.rb +2 -2
- data/app/models/spree/address.rb +13 -17
- data/app/models/spree/adjustment.rb +20 -9
- data/app/models/spree/asset.rb +1 -1
- data/app/models/spree/base.rb +0 -2
- data/app/models/spree/calculator.rb +1 -1
- data/app/models/spree/calculator/price_sack.rb +1 -1
- data/app/models/spree/calculator/shipping/flexi_rate.rb +2 -2
- data/app/models/spree/calculator/tiered_flat_rate.rb +5 -5
- data/app/models/spree/calculator/tiered_percent.rb +6 -6
- data/app/models/spree/carton.rb +3 -3
- data/app/models/spree/classification.rb +2 -2
- data/app/models/spree/credit_card.rb +4 -4
- data/app/models/spree/customer_return.rb +1 -1
- data/app/models/spree/image/paperclip_attachment.rb +1 -1
- data/app/models/spree/inventory_unit.rb +5 -23
- data/app/models/spree/line_item.rb +4 -4
- data/app/models/spree/line_item_action.rb +2 -2
- data/app/models/spree/log_entry.rb +1 -1
- data/app/models/spree/option_value.rb +1 -1
- data/app/models/spree/option_values_variant.rb +2 -2
- data/app/models/spree/order.rb +11 -27
- data/app/models/spree/order/checkout.rb +1 -1
- data/app/models/spree/order/payments.rb +2 -2
- data/app/models/spree/order_cancellations.rb +1 -1
- data/app/models/spree/order_capturing.rb +2 -2
- data/app/models/spree/order_contents.rb +2 -2
- data/app/models/spree/order_mutex.rb +1 -1
- data/app/models/spree/order_promotion.rb +3 -3
- data/app/models/spree/order_shipping.rb +1 -1
- data/app/models/spree/order_taxation.rb +3 -3
- data/app/models/spree/payment.rb +8 -45
- data/app/models/spree/payment/processing.rb +3 -3
- data/app/models/spree/payment_capture_event.rb +1 -1
- data/app/models/spree/payment_method.rb +5 -2
- data/app/models/spree/payment_method/bogus_credit_card.rb +1 -1
- data/app/models/spree/payment_source.rb +1 -1
- data/app/models/spree/price.rb +2 -2
- data/app/models/spree/product.rb +5 -5
- data/app/models/spree/product/scopes.rb +218 -210
- data/app/models/spree/product_option_type.rb +2 -2
- data/app/models/spree/product_promotion_rule.rb +2 -2
- data/app/models/spree/product_property.rb +2 -2
- data/app/models/spree/promotion.rb +28 -13
- data/app/models/spree/promotion/actions/create_quantity_adjustments.rb +1 -1
- data/app/models/spree/promotion/actions/free_shipping.rb +1 -1
- data/app/models/spree/promotion/rules/option_value.rb +2 -2
- data/app/models/spree/promotion/rules/product.rb +3 -3
- data/app/models/spree/promotion_action.rb +2 -2
- data/app/models/spree/promotion_chooser.rb +2 -2
- data/app/models/spree/promotion_code.rb +11 -10
- data/app/models/spree/promotion_code/batch_builder.rb +3 -3
- data/app/models/spree/promotion_code_batch.rb +1 -1
- data/app/models/spree/promotion_rule.rb +2 -2
- data/app/models/spree/promotion_rule_role.rb +2 -2
- data/app/models/spree/promotion_rule_store.rb +2 -2
- data/app/models/spree/promotion_rule_taxon.rb +2 -2
- data/app/models/spree/promotion_rule_user.rb +2 -2
- data/app/models/spree/refund.rb +5 -5
- data/app/models/spree/reimbursement.rb +5 -13
- data/app/models/spree/reimbursement/credit.rb +2 -2
- data/app/models/spree/reimbursement/reimbursement_type_engine.rb +1 -1
- data/app/models/spree/reimbursement_tax_calculator.rb +1 -1
- data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +2 -2
- data/app/models/spree/return_authorization.rb +4 -10
- data/app/models/spree/return_item.rb +13 -52
- data/app/models/spree/return_item/eligibility_validator/default.rb +1 -1
- data/app/models/spree/role_user.rb +2 -2
- data/app/models/spree/shipment.rb +7 -41
- data/app/models/spree/shipping_calculator.rb +0 -4
- data/app/models/spree/shipping_manifest.rb +3 -3
- data/app/models/spree/shipping_method.rb +2 -2
- data/app/models/spree/shipping_method_category.rb +2 -2
- data/app/models/spree/shipping_method_stock_location.rb +2 -2
- data/app/models/spree/shipping_method_zone.rb +2 -2
- data/app/models/spree/shipping_rate.rb +2 -2
- data/app/models/spree/shipping_rate_tax.rb +2 -2
- data/app/models/spree/state.rb +2 -2
- data/app/models/spree/state_change.rb +2 -2
- data/app/models/spree/stock/differentiator.rb +1 -1
- data/app/models/spree/stock/package.rb +1 -1
- data/app/models/spree/stock_item.rb +3 -3
- data/app/models/spree/stock_location.rb +2 -2
- data/app/models/spree/stock_movement.rb +2 -2
- data/app/models/spree/stock_quantities.rb +13 -12
- data/app/models/spree/store_credit.rb +8 -8
- data/app/models/spree/store_credit_event.rb +3 -3
- data/app/models/spree/store_payment_method.rb +2 -2
- data/app/models/spree/store_shipping_method.rb +2 -2
- data/app/models/spree/tax_calculator/default.rb +0 -4
- data/app/models/spree/tax_calculator/shipping_rate.rb +0 -3
- data/app/models/spree/tax_rate.rb +5 -1
- data/app/models/spree/tax_rate_tax_category.rb +2 -2
- data/app/models/spree/taxon/paperclip_attachment.rb +13 -0
- data/app/models/spree/unit_cancel.rb +5 -2
- data/app/models/spree/user_address.rb +2 -2
- data/app/models/spree/user_last_url_storer.rb +46 -0
- data/app/models/spree/user_last_url_storer/rules/authentication_rule.rb +36 -0
- data/app/models/spree/user_stock_location.rb +2 -2
- data/app/models/spree/variant.rb +10 -10
- data/app/models/spree/variant/scopes.rb +37 -29
- data/app/models/spree/variant_property_rule.rb +1 -1
- data/app/models/spree/variant_property_rule_condition.rb +2 -2
- data/app/models/spree/variant_property_rule_value.rb +2 -2
- data/app/models/spree/wallet/add_payment_sources_to_wallet.rb +1 -1
- data/app/models/spree/wallet_payment_source.rb +2 -2
- data/app/models/spree/zone.rb +1 -1
- data/app/models/spree/zone_member.rb +2 -2
- data/config/initializers/inflections.rb +5 -0
- data/config/initializers/money.rb +2 -0
- data/config/locales/en.yml +34 -3
- data/lib/generators/spree/dummy/dummy_generator.rb +2 -0
- data/lib/generators/spree/install/templates/config/initializers/spree.rb.tt +8 -0
- data/lib/spree/app_configuration.rb +18 -3
- data/lib/spree/core.rb +12 -0
- data/lib/spree/core/controller_helpers/auth.rb +1 -13
- data/lib/spree/core/controller_helpers/strong_parameters.rb +21 -7
- data/lib/spree/core/engine.rb +2 -2
- data/lib/spree/core/importer/order.rb +29 -28
- data/lib/spree/core/importer/product.rb +2 -2
- data/lib/spree/core/product_filters.rb +15 -15
- data/lib/spree/core/role_configuration.rb +2 -2
- data/lib/spree/core/search/variant.rb +1 -1
- data/lib/spree/core/state_machines.rb +78 -0
- data/lib/spree/core/state_machines/inventory_unit.rb +42 -0
- data/lib/spree/core/state_machines/payment.rb +61 -0
- data/lib/spree/core/state_machines/reimbursement.rb +33 -0
- data/lib/spree/core/state_machines/return_authorization.rb +32 -0
- data/lib/spree/core/state_machines/return_item/acceptance_status.rb +51 -0
- data/lib/spree/core/state_machines/return_item/reception_status.rb +42 -0
- data/lib/spree/core/state_machines/shipment.rb +58 -0
- data/lib/spree/core/stock_configuration.rb +1 -0
- data/lib/spree/core/validators/email.rb +1 -8
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/money.rb +2 -2
- data/lib/spree/permission_sets/default_customer.rb +1 -1
- data/lib/spree/permission_sets/user_management.rb +3 -0
- data/lib/spree/permitted_attributes.rb +78 -9
- data/lib/spree/preferences/static_model_preferences.rb +2 -2
- data/lib/spree/testing_support/dummy_app.rb +4 -1
- data/lib/spree/testing_support/dummy_app/rake_tasks.rb +6 -2
- data/lib/spree/testing_support/factories/inventory_unit_factory.rb +8 -1
- data/lib/spree/testing_support/factories/promotion_factory.rb +7 -0
- data/lib/spree/testing_support/factories/stock_package_factory.rb +1 -1
- data/lib/spree/testing_support/factories/user_factory.rb +4 -1
- data/solidus_core.gemspec +6 -6
- data/spec/lib/search/base_spec.rb +5 -1
- data/spec/lib/search/variant_spec.rb +1 -1
- data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +8 -1
- data/spec/lib/spree/core/stock_configuration_spec.rb +36 -0
- data/spec/lib/spree/core/validators/email_spec.rb +18 -18
- data/spec/lib/spree/event_spec.rb +15 -3
- data/spec/lib/spree/permitted_attributes_spec.rb +41 -0
- data/spec/models/spree/ability_spec.rb +1 -1
- data/spec/models/spree/address_spec.rb +23 -0
- data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +1 -1
- data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +1 -1
- data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +1 -1
- data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +2 -2
- data/spec/models/spree/calculator/shipping/per_item_spec.rb +1 -1
- data/spec/models/spree/calculator/shipping/price_sack_spec.rb +24 -15
- data/spec/models/spree/carton_spec.rb +10 -2
- data/spec/models/spree/classification_spec.rb +21 -9
- data/spec/models/spree/concerns/user_address_book_spec.rb +4 -4
- data/spec/models/spree/concerns/user_methods_spec.rb +5 -4
- data/spec/models/spree/credit_card_spec.rb +2 -2
- data/spec/models/spree/customer_return_spec.rb +1 -1
- data/spec/models/spree/order/checkout_spec.rb +1 -1
- data/spec/models/spree/order/outstanding_balance_integration_spec.rb +5 -5
- data/spec/models/spree/order/payment_spec.rb +1 -1
- data/spec/models/spree/order_contents_spec.rb +1 -1
- data/spec/models/spree/order_inventory_spec.rb +3 -3
- data/spec/models/spree/order_merger_spec.rb +3 -3
- data/spec/models/spree/order_shipping_spec.rb +1 -1
- data/spec/models/spree/order_spec.rb +14 -21
- data/spec/models/spree/order_updater_spec.rb +4 -3
- data/spec/models/spree/payment_create_spec.rb +6 -16
- data/spec/models/spree/payment_spec.rb +12 -12
- data/spec/models/spree/permission_sets/user_management_spec.rb +2 -0
- data/spec/models/spree/preference_spec.rb +4 -4
- data/spec/models/spree/preferences/preferable_spec.rb +3 -3
- data/spec/models/spree/preferences/statically_configurable_spec.rb +2 -2
- data/spec/models/spree/promotion/rules/first_repeat_purchase_since_spec.rb +2 -2
- data/spec/models/spree/promotion/rules/nth_order_spec.rb +2 -2
- data/spec/models/spree/promotion/rules/taxon_spec.rb +1 -0
- data/spec/models/spree/promotion_rule_spec.rb +6 -6
- data/spec/models/spree/promotion_spec.rb +71 -54
- data/spec/models/spree/reimbursement_type/original_payment_spec.rb +3 -3
- data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +1 -1
- data/spec/models/spree/return_item_spec.rb +11 -11
- data/spec/models/spree/returns_calculator_spec.rb +2 -2
- data/spec/models/spree/shipment_spec.rb +6 -6
- data/spec/models/spree/shipping_calculator_spec.rb +1 -13
- data/spec/models/spree/shipping_method_spec.rb +32 -0
- data/spec/models/spree/stock/availability_validator_spec.rb +2 -2
- data/spec/models/spree/stock/differentiator_spec.rb +2 -2
- data/spec/models/spree/stock/estimator_spec.rb +3 -3
- data/spec/models/spree/stock/inventory_units_finalizer_spec.rb +4 -4
- data/spec/models/spree/stock/package_spec.rb +28 -28
- data/spec/models/spree/stock/quantifier_spec.rb +2 -2
- data/spec/models/spree/stock/simple_coordinator_spec.rb +11 -11
- data/spec/models/spree/stock/splitter/base_spec.rb +4 -4
- data/spec/models/spree/stock/splitter/shipping_category_spec.rb +7 -7
- data/spec/models/spree/stock_quantities_spec.rb +1 -1
- data/spec/models/spree/store_credit_spec.rb +8 -8
- data/spec/models/spree/tax_category_spec.rb +1 -1
- data/spec/models/spree/tax_rate_spec.rb +1 -0
- data/spec/models/spree/taxon_spec.rb +2 -2
- data/spec/models/spree/taxons/paperclip_attachment_spec.rb +29 -0
- data/spec/models/spree/unit_cancel_spec.rb +5 -0
- data/spec/models/spree/user_last_url_storer/rules/authentication_rule_spec.rb +31 -0
- data/spec/models/spree/user_last_url_storer_spec.rb +60 -0
- data/spec/models/spree/user_spec.rb +3 -3
- metadata +46 -39
- data/spec/migrate/20190106184413_remove_code_from_spree_promotions_spec.rb +0 -148
- data/spec/models/spree/order/updating_spec.rb +0 -18
@@ -2,159 +2,162 @@
|
|
2
2
|
|
3
3
|
module Spree
|
4
4
|
class Product < Spree::Base
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
module Scopes
|
6
|
+
def self.prepended(base)
|
7
|
+
base.class_eval do
|
8
|
+
cattr_accessor :search_scopes do
|
9
|
+
[]
|
10
|
+
end
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
def self.add_search_scope(name, &block)
|
13
|
+
singleton_class.send(:define_method, name.to_sym, &block)
|
14
|
+
search_scopes << name.to_sym
|
15
|
+
end
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
def self.property_conditions(property)
|
18
|
+
properties = Property.table_name
|
19
|
+
case property
|
20
|
+
when String then { "#{properties}.name" => property }
|
21
|
+
when Property then { "#{properties}.id" => property.id }
|
22
|
+
else { "#{properties}.id" => property.to_i }
|
23
|
+
end
|
24
|
+
end
|
22
25
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
scope :ascend_by_updated_at, -> { order(updated_at: :asc) }
|
27
|
+
scope :descend_by_updated_at, -> { order(updated_at: :desc) }
|
28
|
+
scope :ascend_by_name, -> { order(name: :asc) }
|
29
|
+
scope :descend_by_name, -> { order(name: :desc) }
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
add_search_scope :ascend_by_master_price do
|
32
|
+
joins(master: :default_price).order(Spree::Price.arel_table[:amount].asc)
|
33
|
+
end
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
+
add_search_scope :descend_by_master_price do
|
36
|
+
joins(master: :default_price).order(Spree::Price.arel_table[:amount].desc)
|
37
|
+
end
|
35
38
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
add_search_scope :price_between do |low, high|
|
40
|
+
joins(master: :default_price).where(Price.table_name => { amount: low..high })
|
41
|
+
end
|
39
42
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
+
add_search_scope :master_price_lte do |price|
|
44
|
+
joins(master: :default_price).where("#{price_table_name}.amount <= ?", price)
|
45
|
+
end
|
43
46
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
+
add_search_scope :master_price_gte do |price|
|
48
|
+
joins(master: :default_price).where("#{price_table_name}.amount >= ?", price)
|
49
|
+
end
|
47
50
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
51
|
+
# This scope selects products in taxon AND all its descendants
|
52
|
+
# If you need products only within one taxon use
|
53
|
+
#
|
54
|
+
# Spree::Product.joins(:taxons).where(Taxon.table_name => { id: taxon.id })
|
55
|
+
#
|
56
|
+
# If you're using count on the result of this scope, you must use the
|
57
|
+
# `:distinct` option as well:
|
58
|
+
#
|
59
|
+
# Spree::Product.in_taxon(taxon).count(distinct: true)
|
60
|
+
#
|
61
|
+
# This is so that the count query is distinct'd:
|
62
|
+
#
|
63
|
+
# SELECT COUNT(DISTINCT "spree_products"."id") ...
|
64
|
+
#
|
65
|
+
# vs.
|
66
|
+
#
|
67
|
+
# SELECT COUNT(*) ...
|
68
|
+
add_search_scope :in_taxon do |taxon|
|
69
|
+
includes(:classifications)
|
70
|
+
.where('spree_products_taxons.taxon_id' => taxon.self_and_descendants.pluck(:id))
|
71
|
+
.select(Spree::Classification.arel_table[:position])
|
72
|
+
.order(Spree::Classification.arel_table[:position].asc)
|
73
|
+
end
|
71
74
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
75
|
+
# This scope selects products in all taxons AND all its descendants
|
76
|
+
# If you need products only within one taxon use
|
77
|
+
#
|
78
|
+
# Spree::Product.taxons_id_eq([x,y])
|
79
|
+
add_search_scope :in_taxons do |*taxons|
|
80
|
+
taxons = get_taxons(taxons)
|
81
|
+
taxons.first ? prepare_taxon_conditions(taxons) : where(nil)
|
82
|
+
end
|
80
83
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
84
|
+
# a scope that finds all products having property specified by name, object or id
|
85
|
+
add_search_scope :with_property do |property|
|
86
|
+
joins(:properties).where(property_conditions(property))
|
87
|
+
end
|
85
88
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
89
|
+
# a simple test for product with a certain property-value pairing
|
90
|
+
# note that it can test for properties with NULL values, but not for absent values
|
91
|
+
add_search_scope :with_property_value do |property, value|
|
92
|
+
joins(:properties)
|
93
|
+
.where("#{Spree::ProductProperty.table_name}.value = ?", value)
|
94
|
+
.where(property_conditions(property))
|
95
|
+
end
|
93
96
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
97
|
+
add_search_scope :with_option do |option|
|
98
|
+
option_types = Spree::OptionType.table_name
|
99
|
+
conditions = case option
|
100
|
+
when String then { "#{option_types}.name" => option }
|
101
|
+
when OptionType then { "#{option_types}.id" => option.id }
|
102
|
+
else { "#{option_types}.id" => option.to_i }
|
103
|
+
end
|
101
104
|
|
102
|
-
|
103
|
-
|
105
|
+
joins(:option_types).where(conditions)
|
106
|
+
end
|
104
107
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
108
|
+
add_search_scope :with_option_value do |option, value|
|
109
|
+
option_values = Spree::OptionValue.table_name
|
110
|
+
option_type_id = case option
|
111
|
+
when String then Spree::OptionType.find_by(name: option) || option.to_i
|
112
|
+
when Spree::OptionType then option.id
|
113
|
+
else option.to_i
|
114
|
+
end
|
112
115
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
+
conditions = "#{option_values}.name = ? AND #{option_values}.option_type_id = ?", value, option_type_id
|
117
|
+
group('spree_products.id').joins(variants_including_master: :option_values).where(conditions)
|
118
|
+
end
|
116
119
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
120
|
+
# Finds all products which have either:
|
121
|
+
# 1) have an option value with the name matching the one given
|
122
|
+
# 2) have a product property with a value matching the one given
|
123
|
+
add_search_scope :with do |value|
|
124
|
+
includes(variants_including_master: :option_values).
|
125
|
+
includes(:product_properties).
|
126
|
+
where("#{Spree::OptionValue.table_name}.name = ? OR #{Spree::ProductProperty.table_name}.value = ?", value, value)
|
127
|
+
end
|
125
128
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
129
|
+
# Finds all products that have a name containing the given words.
|
130
|
+
add_search_scope :in_name do |words|
|
131
|
+
like_any([:name], prepare_words(words))
|
132
|
+
end
|
130
133
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
134
|
+
# Finds all products that have a name or meta_keywords containing the given words.
|
135
|
+
add_search_scope :in_name_or_keywords do |words|
|
136
|
+
like_any([:name, :meta_keywords], prepare_words(words))
|
137
|
+
end
|
135
138
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
139
|
+
# Finds all products that have a name, description, meta_description or meta_keywords containing the given keywords.
|
140
|
+
add_search_scope :in_name_or_description do |words|
|
141
|
+
like_any([:name, :description, :meta_description, :meta_keywords], prepare_words(words))
|
142
|
+
end
|
140
143
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
144
|
+
# Finds all products that have the ids matching the given collection of ids.
|
145
|
+
# Alternatively, you could use find(collection_of_ids), but that would raise an exception if one product couldn't be found
|
146
|
+
add_search_scope :with_ids do |*ids|
|
147
|
+
where(id: ids)
|
148
|
+
end
|
146
149
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
150
|
+
# Sorts products from most popular (popularity is extracted from how many
|
151
|
+
# times use has put product in cart, not completed orders)
|
152
|
+
#
|
153
|
+
# there is alternative faster and more elegant solution, it has small drawback though,
|
154
|
+
# it doesn stack with other scopes :/
|
155
|
+
#
|
156
|
+
# joins: "LEFT OUTER JOIN (SELECT line_items.variant_id as vid, COUNT(*) as cnt FROM line_items GROUP BY line_items.variant_id) AS popularity_count ON variants.id = vid",
|
157
|
+
# order: 'COALESCE(cnt, 0) DESC'
|
158
|
+
add_search_scope :descend_by_popularity do
|
159
|
+
joins(:master).
|
160
|
+
order(%{
|
158
161
|
COALESCE((
|
159
162
|
SELECT
|
160
163
|
COUNT(#{Spree::LineItem.quoted_table_name}.id)
|
@@ -168,93 +171,98 @@ module Spree
|
|
168
171
|
popular_variants.product_id = #{Spree::Product.quoted_table_name}.id
|
169
172
|
), 0) DESC
|
170
173
|
})
|
171
|
-
|
172
|
-
|
173
|
-
add_search_scope :not_deleted do
|
174
|
-
where("#{Spree::Product.quoted_table_name}.deleted_at IS NULL or #{Spree::Product.quoted_table_name}.deleted_at >= ?", Time.current)
|
175
|
-
end
|
176
|
-
|
177
|
-
scope :with_master_price, -> do
|
178
|
-
joins(:master).where(Spree::Price.where(Spree::Variant.arel_table[:id].eq(Spree::Price.arel_table[:variant_id])).arel.exists)
|
179
|
-
end
|
180
|
-
|
181
|
-
# Can't use add_search_scope for this as it needs a default argument
|
182
|
-
def self.available(available_on = nil)
|
183
|
-
with_master_price.where("#{Spree::Product.quoted_table_name}.available_on <= ?", available_on || Time.current)
|
184
|
-
end
|
185
|
-
search_scopes << :available
|
186
|
-
|
187
|
-
add_search_scope :taxons_name_eq do |name|
|
188
|
-
group("spree_products.id").joins(:taxons).where(Spree::Taxon.arel_table[:name].eq(name))
|
189
|
-
end
|
190
|
-
|
191
|
-
def self.with_variant_sku_cont(sku)
|
192
|
-
sku_match = "%#{sku}%"
|
193
|
-
variant_table = Spree::Variant.arel_table
|
194
|
-
subquery = Spree::Variant.where(variant_table[:sku].matches(sku_match).and(variant_table[:product_id].eq(arel_table[:id])))
|
195
|
-
where(subquery.arel.exists)
|
196
|
-
end
|
174
|
+
end
|
197
175
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
sort_column = sort_order.split(" ").first
|
202
|
-
|
203
|
-
# Postgres will complain when using ordering by expressions not present in
|
204
|
-
# SELECT DISTINCT. e.g.
|
205
|
-
#
|
206
|
-
# PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY
|
207
|
-
# expressions must appear in select list. e.g.
|
208
|
-
#
|
209
|
-
# SELECT DISTINCT "spree_products".* FROM "spree_products" LEFT OUTER JOIN
|
210
|
-
# "spree_variants" ON "spree_variants"."product_id" = "spree_products"."id" AND "spree_variants"."is_master" = 't'
|
211
|
-
# AND "spree_variants"."deleted_at" IS NULL LEFT OUTER JOIN "spree_prices" ON
|
212
|
-
# "spree_prices"."variant_id" = "spree_variants"."id" AND "spree_prices"."currency" = 'USD'
|
213
|
-
# AND "spree_prices"."deleted_at" IS NULL WHERE "spree_products"."deleted_at" IS NULL AND ('t'='t')
|
214
|
-
# ORDER BY "spree_prices"."amount" ASC LIMIT 10 OFFSET 0
|
215
|
-
#
|
216
|
-
# Don't allow sort_column, a variable coming from params,
|
217
|
-
# to be anything but a column in the database
|
218
|
-
if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' && !column_names.include?(sort_column)
|
219
|
-
all
|
220
|
-
else
|
221
|
-
distinct
|
222
|
-
end
|
223
|
-
end
|
176
|
+
add_search_scope :not_deleted do
|
177
|
+
where("#{Spree::Product.quoted_table_name}.deleted_at IS NULL or #{Spree::Product.quoted_table_name}.deleted_at >= ?", Time.current)
|
178
|
+
end
|
224
179
|
|
225
|
-
|
226
|
-
|
180
|
+
scope :with_master_price, -> do
|
181
|
+
joins(:master).where(Spree::Price.where(Spree::Variant.arel_table[:id].eq(Spree::Price.arel_table[:variant_id])).arel.exists)
|
182
|
+
end
|
183
|
+
# Can't use add_search_scope for this as it needs a default argument
|
184
|
+
def self.available(available_on = nil)
|
185
|
+
with_master_price.where("#{Spree::Product.quoted_table_name}.available_on <= ?", available_on || Time.current)
|
186
|
+
end
|
187
|
+
search_scopes << :available
|
227
188
|
|
228
|
-
|
229
|
-
|
230
|
-
|
189
|
+
add_search_scope :taxons_name_eq do |name|
|
190
|
+
group("spree_products.id").joins(:taxons).where(Spree::Taxon.arel_table[:name].eq(name))
|
191
|
+
end
|
231
192
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
193
|
+
def self.with_variant_sku_cont(sku)
|
194
|
+
sku_match = "%#{sku}%"
|
195
|
+
variant_table = Spree::Variant.arel_table
|
196
|
+
subquery = Spree::Variant.where(variant_table[:sku].matches(sku_match).and(variant_table[:product_id].eq(arel_table[:id])))
|
197
|
+
where(subquery.arel.exists)
|
198
|
+
end
|
237
199
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
200
|
+
def self.distinct_by_product_ids(sort_order = nil)
|
201
|
+
Spree::Deprecation.warn "Product.distinct_by_product_ids is deprecated and should not be used"
|
202
|
+
|
203
|
+
sort_column = sort_order.split(" ").first
|
204
|
+
|
205
|
+
# Postgres will complain when using ordering by expressions not present in
|
206
|
+
# SELECT DISTINCT. e.g.
|
207
|
+
#
|
208
|
+
# PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY
|
209
|
+
# expressions must appear in select list. e.g.
|
210
|
+
#
|
211
|
+
# SELECT DISTINCT "spree_products".* FROM "spree_products" LEFT OUTER JOIN
|
212
|
+
# "spree_variants" ON "spree_variants"."product_id" = "spree_products"."id" AND "spree_variants"."is_master" = 't'
|
213
|
+
# AND "spree_variants"."deleted_at" IS NULL LEFT OUTER JOIN "spree_prices" ON
|
214
|
+
# "spree_prices"."variant_id" = "spree_variants"."id" AND "spree_prices"."currency" = 'USD'
|
215
|
+
# AND "spree_prices"."deleted_at" IS NULL WHERE "spree_products"."deleted_at" IS NULL AND ('t'='t')
|
216
|
+
# ORDER BY "spree_prices"."amount" ASC LIMIT 10 OFFSET 0
|
217
|
+
#
|
218
|
+
# Don't allow sort_column, a variable coming from params,
|
219
|
+
# to be anything but a column in the database
|
220
|
+
if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' && !column_names.include?(sort_column)
|
221
|
+
all
|
222
|
+
else
|
223
|
+
distinct
|
224
|
+
end
|
225
|
+
end
|
245
226
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
227
|
+
class << self
|
228
|
+
private
|
229
|
+
|
230
|
+
def price_table_name
|
231
|
+
Spree::Price.quoted_table_name
|
232
|
+
end
|
233
|
+
|
234
|
+
# specifically avoid having an order for taxon search (conflicts with main order)
|
235
|
+
def prepare_taxon_conditions(taxons)
|
236
|
+
ids = taxons.map { |taxon| taxon.self_and_descendants.pluck(:id) }.flatten.uniq
|
237
|
+
joins(:taxons).where("#{Spree::Taxon.table_name}.id" => ids)
|
238
|
+
end
|
239
|
+
|
240
|
+
# Produce an array of keywords for use in scopes.
|
241
|
+
# Always return array with at least an empty string to avoid SQL errors
|
242
|
+
def prepare_words(words)
|
243
|
+
return [''] if words.blank?
|
244
|
+
|
245
|
+
splitted = words.split(/[,\s]/).map(&:strip)
|
246
|
+
splitted.any? ? splitted : ['']
|
247
|
+
end
|
248
|
+
|
249
|
+
def get_taxons(*ids_or_records_or_names)
|
250
|
+
taxons = Spree::Taxon.table_name
|
251
|
+
ids_or_records_or_names.flatten.map { |taxon|
|
252
|
+
case taxon
|
253
|
+
when Integer then Spree::Taxon.find_by(id: taxon)
|
254
|
+
when ActiveRecord::Base then taxon
|
255
|
+
when String
|
256
|
+
Spree::Taxon.find_by(name: taxon) ||
|
257
|
+
Spree::Taxon.where("#{taxons}.permalink LIKE ? OR #{taxons}.permalink = ?", "%/#{taxon}/", "#{taxon}/").first
|
258
|
+
end
|
259
|
+
}.compact.flatten.uniq
|
260
|
+
end
|
255
261
|
end
|
256
|
-
|
262
|
+
end
|
257
263
|
end
|
264
|
+
|
265
|
+
::Spree::Product.prepend self
|
258
266
|
end
|
259
267
|
end
|
260
268
|
end
|