solidus_core 2.9.5 → 2.10.2
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/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
|