spree_core 4.0.8 → 4.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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/configuration/active_storage.rb +9 -1
  12. data/app/models/spree/image.rb +52 -3
  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/address_book.rb +20 -7
  16. data/app/models/spree/order.rb +12 -12
  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 +3 -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/controller_helpers/order.rb +12 -6
  46. data/lib/spree/core/controller_helpers/store.rb +2 -2
  47. data/lib/spree/core/search/base.rb +59 -22
  48. data/lib/spree/core/version.rb +1 -3
  49. data/lib/spree/core.rb +0 -1
  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 -52
  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 +9 -15
  57. metadata +49 -34
  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: 588155cb249e1eefd8e5c6ae2e6945618789083950c80c871d6edf1301816335
4
- data.tar.gz: e8d545d4df554f51f6c3e23bb11da7174b78e73285d2ca58106df76f95971fb8
3
+ metadata.gz: db73357d472e46822ad95d6ee2071b01413e2f1ab743177f7cfc8845c6830092
4
+ data.tar.gz: 83c396103e3809183ac12c21f72e4831cb2c10d1089232bdecd58395459a961b
5
5
  SHA512:
6
- metadata.gz: ef4fcece6d37dfe33965151bfdb649985a343498bd1b028143deee6d1c34a9203e8d799424ccd68bca8d1fd2ea40ff9285c3f7fa4035c6b1338c0fcd3d33863b
7
- data.tar.gz: ae4a54b8c2732465955b5039faafb25bc4e22b5b3f723c928eaadca424f6dd06b5549fbd35ebc730baaae0e4083c4b891c35de336f5bc0e2bd2e2e62758865ca
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
 
@@ -15,7 +15,15 @@ module Spree
15
15
  mini: '48x48>',
16
16
  small: '100x100>',
17
17
  product: '240x240>',
18
- large: '600x600>'
18
+ pdp_thumbnail: '160x200>',
19
+ plp_and_carousel: '448x600>',
20
+ plp_and_carousel_xs: '254x340>',
21
+ plp_and_carousel_sm: '350x468>',
22
+ plp_and_carousel_md: '222x297>',
23
+ plp_and_carousel_lg: '278x371>',
24
+ large: '600x600>',
25
+ plp: '278x371>',
26
+ zoomed: '650x870>'
19
27
  }
20
28
  end
21
29
 
@@ -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
@@ -59,8 +59,7 @@ module Spree
59
59
 
60
60
  extend DisplayMoney
61
61
  money_methods :amount, :subtotal, :discounted_amount, :final_amount, :total, :price,
62
- :adjustment_total, :additional_tax_total, :promo_total, :included_tax_total,
63
- :pre_tax_amount
62
+ :adjustment_total, :additional_tax_total, :promo_total, :included_tax_total
64
63
 
65
64
  alias single_money display_price
66
65
  alias single_display_amount display_price
@@ -23,6 +23,10 @@ module Spree
23
23
 
24
24
  after_touch :touch_all_products
25
25
 
26
+ def filter_param
27
+ presentation.titleize.delete(' ').downcase
28
+ end
29
+
26
30
  private
27
31
 
28
32
  def touch_all_products
@@ -55,18 +55,31 @@ module Spree
55
55
  def update_or_create_address(attributes = {})
56
56
  return if attributes.blank?
57
57
 
58
- attributes.transform_values! { |v| v == '' ? nil : v }
58
+ attributes = attributes.select { |_k, v| v.present? }
59
59
 
60
- default_address_scope = user ? user.addresses : ::Spree::Address
61
- default_address = default_address_scope.find_by(id: attributes[:id])
60
+ if user
61
+ address = user.addresses.build(attributes.except(:id)).check
62
+ return address if address.id
63
+ end
64
+
65
+ if attributes[:id]
66
+ address = Spree::Address.find(attributes[:id])
67
+ attributes.delete(:id)
62
68
 
63
- if default_address&.editable?
64
- default_address.update(attributes)
69
+ if address&.editable?
70
+ address.update(attributes)
71
+ return address
72
+ else
73
+ attributes.delete(:id)
74
+ end
75
+ end
65
76
 
66
- return default_address
77
+ unless attributes[:id]
78
+ address = Spree::Address.new(attributes)
79
+ address.save
67
80
  end
68
81
 
69
- ::Spree::Address.find_or_create_by(attributes.except(:id, :updated_at, :created_at))
82
+ address
70
83
  end
71
84
  end
72
85
  end
@@ -21,8 +21,7 @@ module Spree
21
21
  extend Spree::DisplayMoney
22
22
  money_methods :outstanding_balance, :item_total, :adjustment_total,
23
23
  :included_tax_total, :additional_tax_total, :tax_total,
24
- :shipment_total, :promo_total, :total,
25
- :cart_promo_total, :pre_tax_item_amount, :pre_tax_total
24
+ :shipment_total, :promo_total, :total
26
25
 
27
26
  alias display_ship_total display_shipment_total
28
27
  alias_attribute :ship_total, :shipment_total
@@ -174,12 +173,7 @@ module Spree
174
173
 
175
174
  # Sum of all line item amounts pre-tax
176
175
  def pre_tax_item_amount
177
- line_items.sum(:pre_tax_amount)
178
- end
179
-
180
- # Sum of all line item and shipment pre-tax
181
- def pre_tax_total
182
- pre_tax_item_amount + shipments.sum(:pre_tax_amount)
176
+ line_items.to_a.sum(&:pre_tax_amount)
183
177
  end
184
178
 
185
179
  def shipping_discount
@@ -375,8 +369,8 @@ module Spree
375
369
  payment_state == 'paid' || payment_state == 'credit_owed'
376
370
  end
377
371
 
378
- def available_payment_methods
379
- @available_payment_methods ||= collect_payment_methods
372
+ def available_payment_methods(store = nil)
373
+ @available_payment_methods ||= collect_payment_methods(store)
380
374
  end
381
375
 
382
376
  def insufficient_stock_lines
@@ -631,6 +625,12 @@ module Spree
631
625
  all_adjustments.eligible.nonzero.promotion.map { |a| a.source.promotion_id }.uniq
632
626
  end
633
627
 
628
+ def valid_coupon_promotions
629
+ promotions.
630
+ where(id: valid_promotion_ids).
631
+ coupons
632
+ end
633
+
634
634
  private
635
635
 
636
636
  def link_by_email
@@ -689,8 +689,8 @@ module Spree
689
689
  self.token ||= generate_token
690
690
  end
691
691
 
692
- def collect_payment_methods
693
- PaymentMethod.available_on_front_end.select { |pm| pm.available_for_order?(self) }
692
+ def collect_payment_methods(store = nil)
693
+ PaymentMethod.available_on_front_end.select { |pm| pm.available_for_order?(self) && pm.available_for_store?(store) }
694
694
  end
695
695
 
696
696
  def credit_card_nil_payment?(attributes)
@@ -12,6 +12,8 @@ module Spree
12
12
 
13
13
  validates :name, presence: true
14
14
 
15
+ belongs_to :store
16
+
15
17
  with_options dependent: :restrict_with_error do
16
18
  has_many :payments, class_name: 'Spree::Payment', inverse_of: :payment_method
17
19
  has_many :credit_cards, class_name: 'Spree::CreditCard'
@@ -75,5 +77,11 @@ module Spree
75
77
  def available_for_order?(_order)
76
78
  true
77
79
  end
80
+
81
+ def available_for_store?(store)
82
+ return true if store.blank? || store_id.blank?
83
+
84
+ store_id == store.id
85
+ end
78
86
  end
79
87
  end
@@ -100,7 +100,7 @@ module Spree::Preferences::Preferable
100
100
  if value.is_a?(FalseClass) ||
101
101
  value.nil? ||
102
102
  value == 0 ||
103
- value&.to_s =~ /^(f|false|0)$/i ||
103
+ value =~ /^(f|false|0)$/i ||
104
104
  (value.respond_to?(:empty?) && value.empty?)
105
105
  false
106
106
  else