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