spree_core 4.0.7 → 4.1.0.rc1

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/spree.js +0 -1
  3. data/app/finders/spree/products/find.rb +19 -6
  4. data/app/finders/spree/variants/option_types_finder.rb +21 -0
  5. data/app/finders/spree/variants/visible_finder.rb +22 -0
  6. data/app/helpers/spree/base_helper.rb +48 -18
  7. data/app/helpers/spree/products_helper.rb +76 -8
  8. data/app/models/concerns/spree/user_methods.rb +2 -2
  9. data/app/models/spree/app_dependencies.rb +1 -7
  10. data/app/models/spree/credit_card.rb +4 -5
  11. data/app/models/spree/image.rb +52 -3
  12. data/app/models/spree/image/configuration/active_storage.rb +9 -1
  13. data/app/models/spree/line_item.rb +1 -2
  14. data/app/models/spree/option_type.rb +4 -0
  15. data/app/models/spree/order.rb +12 -12
  16. data/app/models/spree/order/address_book.rb +20 -7
  17. data/app/models/spree/payment_method.rb +8 -0
  18. data/app/models/spree/preferences/preferable.rb +1 -1
  19. data/app/models/spree/product.rb +7 -6
  20. data/app/models/spree/promotion/actions/create_item_adjustments.rb +1 -1
  21. data/app/models/spree/promotion_handler/coupon.rb +2 -1
  22. data/app/models/spree/return_item/eligibility_validator/base_validator.rb +1 -1
  23. data/app/models/spree/store.rb +2 -1
  24. data/app/models/spree/taxon.rb +2 -6
  25. data/app/models/spree/variant.rb +2 -14
  26. data/app/models/spree/zone.rb +6 -3
  27. data/app/presenters/spree/product_summary_presenter.rb +26 -0
  28. data/app/presenters/spree/variant_presenter.rb +69 -0
  29. data/app/presenters/spree/variants/option_types_presenter.rb +74 -0
  30. data/app/presenters/spree/variants/options_presenter.rb +49 -0
  31. data/app/services/spree/checkout/get_shipping_rates.rb +10 -7
  32. data/app/services/spree/checkout/update.rb +2 -13
  33. data/config/locales/en.yml +156 -14
  34. data/db/default/spree/stores.rb +8 -3
  35. data/db/migrate/20140309033438_create_store_from_preferences.rb +8 -4
  36. data/db/migrate/20191005121504_add_store_id_to_payment_methods.rb +7 -0
  37. data/db/migrate/20191016134113_add_deafult_value_for_store_default_currency.rb +5 -0
  38. data/db/migrate/20200102141311_add_social_to_spree_stores.rb +7 -0
  39. data/lib/generators/spree/dummy/dummy_generator.rb +2 -1
  40. data/lib/generators/spree/dummy/templates/initializers/bullet.rb +5 -0
  41. data/lib/generators/spree/install/install_generator.rb +13 -5
  42. data/lib/generators/spree/install/templates/config/initializers/spree.rb +0 -1
  43. data/lib/generators/spree/install/templates/config/initializers/spree_storefront.rb +1 -0
  44. data/lib/generators/spree/install/templates/config/spree_storefront.yml +67 -0
  45. data/lib/spree/core.rb +0 -1
  46. data/lib/spree/core/controller_helpers/order.rb +12 -6
  47. data/lib/spree/core/controller_helpers/store.rb +2 -2
  48. data/lib/spree/core/search/base.rb +59 -22
  49. data/lib/spree/core/version.rb +1 -3
  50. data/lib/spree/money.rb +8 -1
  51. data/lib/spree/permitted_attributes.rb +3 -2
  52. data/lib/spree/testing_support/capybara_ext.rb +0 -45
  53. data/lib/spree/testing_support/common_rake.rb +1 -1
  54. data/lib/spree/testing_support/factories/store_factory.rb +3 -0
  55. data/lib/spree/testing_support/order_walkthrough.rb +7 -3
  56. data/spree_core.gemspec +8 -14
  57. metadata +45 -24
  58. data/app/finders/spree/addresses/find.rb +0 -17
  59. data/app/services/spree/account/addresses/base.rb +0 -39
  60. data/app/services/spree/account/addresses/create.rb +0 -18
  61. data/app/services/spree/account/addresses/update.rb +0 -18
  62. data/lib/spree/database_type_utilities.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 24d8697b01ebe0da73f0747dc3ddc9a45522db809a92ebc93a97dc9e8c4fccef
4
- data.tar.gz: 691bcf5bba6d78868abb9b39893b63737398dae79d5e939381cc9c02ef6a6286
3
+ metadata.gz: db73357d472e46822ad95d6ee2071b01413e2f1ab743177f7cfc8845c6830092
4
+ data.tar.gz: 83c396103e3809183ac12c21f72e4831cb2c10d1089232bdecd58395459a961b
5
5
  SHA512:
6
- metadata.gz: 79a9d22bd03b122d64e7bf5a2505df120e4671442945eb2c2c0d8a63be3a592f344252730add4fde3bbf757282d9016fb8e2f6cf21b405415b6094d45d0407cf
7
- data.tar.gz: c12bb814fa2b091c153e5ebdc18c33c645ae6e5c40e4d0bf78e2fd36bc712f3017ee7b0149904402bca5376193e496df652a56cfed8486a908ee59b35e4d83ab
6
+ metadata.gz: f57f8d0b1bee1cb0b0d77b7aa82ac8f62d89a783e07dbd1e5f2a8a6d780eaf8de46ccf5e898420d423fe1d133ce2645615cd4611580ca92008d006c059667e1a
7
+ data.tar.gz: 7e3aee2e5bcc514a78dcc8da3cfb5b35635f691fc2fe9ac68002c9cd208bc96b5df4f784da4612cf1ad409dea467e0a5c29cc13e156e25aa7baeb5d72f367f47
@@ -2,7 +2,6 @@
2
2
  function Spree () {}
3
3
 
4
4
  Spree.ready = function (callback) {
5
- jQuery(callback)
6
5
  return jQuery(document).on('page:load turbolinks:load', function () {
7
6
  return callback(jQuery)
8
7
  })
@@ -112,17 +112,30 @@ module Spree
112
112
  def by_options(products)
113
113
  return products unless options?
114
114
 
115
- products.where(
116
- id: options.map do |key, value|
117
- products.with_option_value(key, value).ids
118
- end.flatten.compact.uniq
119
- )
115
+ options.map do |key, value|
116
+ products.with_option_value(key, value)
117
+ end.inject(:&)
120
118
  end
121
119
 
122
120
  def by_option_value_ids(products)
123
121
  return products unless option_value_ids?
124
122
 
125
- products.joins(variants: :option_values).distinct.where(spree_option_values: { id: option_value_ids })
123
+ product_ids = Spree::Product.
124
+ joins(variants: :option_values).
125
+ where(spree_option_values: { id: option_value_ids }).
126
+ group("#{Spree::Product.table_name}.id, #{Spree::Variant.table_name}.id").
127
+ having('COUNT(spree_option_values.option_type_id) = ?', option_types_count(option_value_ids)).
128
+ distinct.
129
+ ids
130
+
131
+ products.where(id: product_ids)
132
+ end
133
+
134
+ def option_types_count(option_value_ids)
135
+ Spree::OptionValue.
136
+ where(id: option_value_ids).
137
+ distinct.
138
+ count(:option_type_id)
126
139
  end
127
140
 
128
141
  def ordered(products)
@@ -0,0 +1,21 @@
1
+ module Spree
2
+ module Variants
3
+ class OptionTypesFinder
4
+ COLOR_TYPE = 'color'.freeze
5
+
6
+ def initialize(variant_ids:)
7
+ @variant_ids = variant_ids
8
+ end
9
+
10
+ def execute
11
+ Spree::OptionType.includes(option_values: :variants).where(spree_variants: { id: variant_ids }).
12
+ reorder('spree_option_types.position ASC, spree_option_values.position ASC').
13
+ partition { |option_type| option_type.name.downcase == COLOR_TYPE }.flatten
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :variant_ids
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ module Spree
2
+ module Variants
3
+ class VisibleFinder
4
+ def initialize(scope:, current_currency:)
5
+ @scope = scope
6
+ @current_currency = current_currency
7
+ end
8
+
9
+ def execute
10
+ Spree::Variant.where(id: active_variants).joins(:option_values).order('spree_option_values.position ASC')
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :scope, :current_currency
16
+
17
+ def active_variants
18
+ scope.active(current_currency).unscope(:order)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -32,8 +32,12 @@ module Spree
32
32
  end
33
33
  end
34
34
 
35
- def logo(image_path = Spree::Config[:logo])
36
- link_to image_tag(image_path), spree.respond_to?(:root_path) ? spree.root_path : main_app.root_path
35
+ def logo(image_path = Spree::Config[:logo], options = {})
36
+ path = spree.respond_to?(:root_path) ? spree.root_path : main_app.root_path
37
+
38
+ link_to path, 'aria-label': current_store.name, method: options[:method] do
39
+ image_tag image_path, alt: current_store.name, title: current_store.name
40
+ end
37
41
  end
38
42
 
39
43
  def meta_data
@@ -50,15 +54,32 @@ module Spree
50
54
  end
51
55
 
52
56
  if meta[:keywords].blank? || meta[:description].blank?
53
- meta.reverse_merge!(keywords: current_store.meta_keywords,
54
- description: current_store.meta_description)
57
+ if object && object[:name].present?
58
+ meta.reverse_merge!(keywords: [object.name, current_store.meta_keywords].reject(&:blank?).join(', '),
59
+ description: [object.name, current_store.meta_description].reject(&:blank?).join(', '))
60
+ else
61
+ meta.reverse_merge!(keywords: (current_store.meta_keywords || current_store.seo_title),
62
+ description: (current_store.meta_description || current_store.seo_title))
63
+ end
55
64
  end
56
65
  meta
57
66
  end
58
67
 
68
+ def meta_image_url_path
69
+ object = instance_variable_get('@' + controller_name.singularize)
70
+ return unless object.is_a?(Spree::Product)
71
+
72
+ image = default_image_for_product_or_variant(object)
73
+ image&.attachment.present? ? main_app.url_for(image.attachment) : asset_path(Spree::Config[:logo])
74
+ end
75
+
76
+ def meta_image_data_tag
77
+ tag('meta', property: 'og:image', content: meta_image_url_path) if meta_image_url_path
78
+ end
79
+
59
80
  def meta_data_tags
60
81
  meta_data.map do |name, content|
61
- tag('meta', name: name, content: content)
82
+ tag('meta', name: name, content: content) unless name.nil? || content.nil?
62
83
  end.join("\n")
63
84
  end
64
85
 
@@ -75,14 +96,30 @@ module Spree
75
96
  [I18n.l(time.to_date, format: :long), time.strftime('%l:%M %p')].join(' ')
76
97
  end
77
98
 
78
- def seo_url(taxon)
79
- spree.nested_taxons_path(taxon.permalink)
99
+ def seo_url(taxon, options = nil)
100
+ spree.nested_taxons_path(taxon.permalink, options)
80
101
  end
81
102
 
82
103
  def frontend_available?
83
104
  Spree::Core::Engine.frontend_available?
84
105
  end
85
106
 
107
+ def default_image_for_product_or_variant(product_or_variant)
108
+ if product_or_variant.images.empty?
109
+ if product_or_variant.is_a?(Spree::Product) && product_or_variant.variant_images.any?
110
+ product_or_variant.variant_images.first
111
+ elsif product_or_variant.is_a?(Spree::Variant) && product_or_variant.product.variant_images.any?
112
+ product_or_variant.product.variant_images.first
113
+ end
114
+ else
115
+ product_or_variant.images.first
116
+ end
117
+ end
118
+
119
+ def base_cache_key
120
+ [I18n.locale, current_currency]
121
+ end
122
+
86
123
  private
87
124
 
88
125
  def create_product_image_tag(image, product, options, style)
@@ -94,18 +131,11 @@ module Spree
94
131
  self.class.send :define_method, "#{style}_image" do |product, *options|
95
132
  options = options.first || {}
96
133
  options[:alt] ||= product.name
97
- if product.images.empty?
98
- if !product.is_a?(Spree::Variant) && !product.variant_images.empty?
99
- create_product_image_tag(product.variant_images.first, product, options, style)
100
- else
101
- if product.is_a?(Variant) && !product.product.variant_images.empty?
102
- create_product_image_tag(product.product.variant_images.first, product, options, style)
103
- else
104
- image_tag "noimage/#{style}.png", options
105
- end
106
- end
134
+ image_path = default_image_for_product_or_variant(product)
135
+ if image_path.present?
136
+ create_product_image_tag image_path, product, options, style
107
137
  else
108
- create_product_image_tag(product.images.first, product, options, style)
138
+ image_tag "noimage/#{style}.png", options
109
139
  end
110
140
  end
111
141
  end
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  module ProductsHelper
3
+ include BaseHelper
4
+
3
5
  # returns the formatted price for the specified variant as a full price or a difference depending on configuration
4
6
  def variant_price(variant)
5
7
  if Spree::Config[:show_variant_full_price]
@@ -29,6 +31,14 @@ module Spree
29
31
  end
30
32
  end
31
33
 
34
+ def default_variant(variants)
35
+ variants_option_types_presenter(variants).default_variant || variants.find(&:is_master)
36
+ end
37
+
38
+ def used_variants_options(variants)
39
+ variants_option_types_presenter(variants).options
40
+ end
41
+
32
42
  # converts line breaks in product description into <p> tags (for html display purposes)
33
43
  def product_description(product)
34
44
  description = if Spree::Config[:show_raw_product_description]
@@ -47,15 +57,27 @@ module Spree
47
57
  end
48
58
  end
49
59
 
50
- def cache_key_for_products
51
- count = @products.count
52
- max_updated_at = (@products.maximum(:updated_at) || Date.today).to_s(:number)
53
- products_cache_keys = "spree/products/all-#{params[:page]}-#{max_updated_at}-#{count}"
54
- (common_product_cache_keys + [products_cache_keys]).compact.join('/')
60
+ def cache_key_for_products(products = @products, additional_cache_key = nil)
61
+ count = products.count
62
+ max_updated_at = (products.maximum(:updated_at) || Date.today).to_s(:number)
63
+ products_cache_keys = "spree/products/all-#{params[:page]}-#{params[:sort_by]}-#{max_updated_at}-#{count}-#{@taxon&.id}"
64
+ (common_product_cache_keys + [products_cache_keys] + [additional_cache_key]).compact.join('/')
55
65
  end
56
66
 
57
67
  def cache_key_for_product(product = @product)
58
- (common_product_cache_keys + [product.cache_key_with_version, product.possible_promotions]).compact.join('/')
68
+ cache_key_elements = common_product_cache_keys
69
+ cache_key_elements += [
70
+ product.cache_key_with_version,
71
+ product.possible_promotions
72
+ ]
73
+
74
+ cache_key_elements.compact.join('/')
75
+ end
76
+
77
+ def limit_descritpion(string)
78
+ return string if string.length <= 450
79
+
80
+ string.slice(0..449) + '...'
59
81
  end
60
82
 
61
83
  def available_status(product) # will return a human readable string
@@ -71,16 +93,62 @@ module Spree
71
93
  end
72
94
  end
73
95
 
74
- private
96
+ def product_images(product, variants)
97
+ variants = if product.variants_and_option_values(current_currency).any?
98
+ variants.reject(&:is_master)
99
+ else
100
+ variants
101
+ end
102
+
103
+ variants.map(&:images).flatten
104
+ end
105
+
106
+ def product_variants_matrix(is_product_available_in_currency)
107
+ Spree::VariantPresenter.new(
108
+ variants: @variants,
109
+ is_product_available_in_currency: is_product_available_in_currency,
110
+ current_currency: current_currency,
111
+ current_price_options: current_price_options
112
+ ).call.to_json
113
+ end
114
+
115
+ def related_products
116
+ return [] unless @product.respond_to?(:has_related_products?) && @product.has_related_products?(:related_products)
117
+
118
+ @_related_products ||= @product.
119
+ related_products.
120
+ includes(
121
+ :tax_category,
122
+ master: [
123
+ :prices,
124
+ images: { attachment_attachment: :blob },
125
+ ]
126
+ ).
127
+ limit(Spree::Config[:products_per_page])
128
+ end
129
+
130
+ def product_available_in_currency?(product)
131
+ !(product.price_in(current_currency).amount.nil? || product.price_in(current_currency).amount.zero?)
132
+ end
75
133
 
76
134
  def common_product_cache_keys
77
- [I18n.locale, current_currency] + price_options_cache_key
135
+ base_cache_key + price_options_cache_key
78
136
  end
79
137
 
138
+ private
139
+
80
140
  def price_options_cache_key
81
141
  current_price_options.sort.map(&:last).map do |value|
82
142
  value.try(:cache_key) || value
83
143
  end
84
144
  end
145
+
146
+ def variants_option_types_presenter(variants)
147
+ @_variants_option_types_presenter ||= begin
148
+ option_types = Spree::Variants::OptionTypesFinder.new(variant_ids: variants.map(&:id)).execute
149
+
150
+ Spree::Variants::OptionTypesPresenter.new(option_types)
151
+ end
152
+ end
85
153
  end
86
154
  end
@@ -47,9 +47,9 @@ module Spree
47
47
  spree_roles.any? { |role| role.name == role_in_question.to_s }
48
48
  end
49
49
 
50
- def last_incomplete_spree_order(store)
50
+ def last_incomplete_spree_order(store, options = {})
51
51
  orders.where(store: store).incomplete.
52
- includes(line_items: [variant: [:images, :option_values, :product]]).
52
+ includes(options[:includes]).
53
53
  order('created_at DESC').
54
54
  first
55
55
  end
@@ -11,8 +11,7 @@ module Spree
11
11
  :checkout_remove_store_credit_service, :checkout_get_shipping_rates_service,
12
12
  :coupon_handler, :country_finder, :current_order_finder, :credit_card_finder,
13
13
  :completed_order_finder, :order_sorter, :cart_compare_line_items_service, :collection_paginator, :products_sorter,
14
- :products_finder, :taxon_finder, :line_item_by_variant_finder, :cart_estimate_shipping_rates_service,
15
- :account_create_address_service, :account_update_address_service, :address_finder
14
+ :products_finder, :taxon_finder, :line_item_by_variant_finder, :cart_estimate_shipping_rates_service
16
15
  ].freeze
17
16
 
18
17
  attr_accessor *INJECTION_POINTS
@@ -60,14 +59,9 @@ module Spree
60
59
  # coupons
61
60
  # TODO: we should split this service into 2 seperate - Add and Remove
62
61
  @coupon_handler = 'Spree::PromotionHandler::Coupon'
63
-
64
- # account
65
- @account_create_address_service = 'Spree::Account::Addresses::Create'
66
- @account_update_address_service = 'Spree::Account::Addresses::Update'
67
62
  end
68
63
 
69
64
  def set_default_finders
70
- @address_finder = 'Spree::Addresses::Find'
71
65
  @country_finder = 'Spree::Countries::Find'
72
66
  @current_order_finder = 'Spree::Orders::FindCurrent'
73
67
  @completed_order_finder = 'Spree::Orders::FindComplete'
@@ -24,9 +24,10 @@ module Spree
24
24
  attribute :month, ActiveRecord::Type::Integer.new
25
25
  attribute :year, ActiveRecord::Type::Integer.new
26
26
 
27
- attr_reader :number, :verification_value
27
+ attr_reader :number
28
28
  attr_accessor :encrypted_data,
29
29
  :imported,
30
+ :verification_value,
30
31
  :manual_entry
31
32
 
32
33
  with_options if: :require_card_numbers?, on: :create do
@@ -100,11 +101,9 @@ module Spree
100
101
  end
101
102
  end
102
103
 
103
- def verification_value=(value)
104
- @verification_value = value.to_s.gsub(/\s/, '')
105
- end
106
-
107
104
  def set_last_digits
105
+ number.to_s.gsub!(/\s/, '')
106
+ verification_value.to_s.gsub!(/\s/, '')
108
107
  self.last_digits ||= number.to_s.length <= 4 ? number : number.to_s.slice(-4..-1)
109
108
  end
110
109
 
@@ -2,7 +2,7 @@ module Spree
2
2
  class Image < Asset
3
3
  include Configuration::ActiveStorage
4
4
  include Rails.application.routes.url_helpers
5
-
5
+
6
6
  # In Rails 5.x class constants are being undefined/redefined during the code reloading process
7
7
  # in a rails development environment, after which the actual ruby objects stored in those class constants
8
8
  # are no longer equal (subclass == self) what causes error ActiveRecord::SubclassNotFound
@@ -12,14 +12,63 @@ module Spree
12
12
 
13
13
  def styles
14
14
  self.class.styles.map do |_, size|
15
- width, height = size[/(\d+)x(\d+)/].split('x')
15
+ width, height = size.chop.split('x')
16
16
 
17
17
  {
18
- url: polymorphic_path(attachment.variant(resize: size), only_path: true),
18
+ url: polymorphic_path(attachment.variant(combine_options: {
19
+ gravity: 'center',
20
+ resize: size,
21
+ extent: size,
22
+ background: 'snow2',
23
+ quality: 80
24
+ }), only_path: true),
19
25
  width: width,
20
26
  height: height
21
27
  }
22
28
  end
23
29
  end
30
+
31
+ def style(name)
32
+ size = self.class.styles[name]
33
+ return unless size
34
+
35
+ width, height = size.chop.split('x')
36
+
37
+ {
38
+ url: polymorphic_path(attachment.variant(combine_options: {
39
+ gravity: 'center',
40
+ resize: size,
41
+ extent: size,
42
+ background: 'snow2',
43
+ quality: 80
44
+ }), only_path: true),
45
+ size: size,
46
+ width: width,
47
+ height: height
48
+ }
49
+ end
50
+
51
+ def style_dimensions(name)
52
+ size = self.class.styles[name]
53
+ width, height = size.chop.split('x')
54
+
55
+ {
56
+ width: width,
57
+ height: height
58
+ }
59
+ end
60
+
61
+ def plp_url
62
+ size = self.class.styles[:plp_and_carousel]
63
+ variant = attachment.variant(
64
+ gravity: 'center',
65
+ resize: size,
66
+ extent: size,
67
+ background: 'snow2',
68
+ quality: 80
69
+ )
70
+
71
+ polymorphic_path(variant, only_path: true)
72
+ end
24
73
  end
25
74
  end