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
@@ -1,10 +1,15 @@
1
1
  # Possibly already created by a migration.
2
- unless Spree::Store.where(code: 'spree').exists?
2
+ unless Spree::Store.default.persisted?
3
3
  Spree::Store.new do |s|
4
- s.code = 'spree'
5
4
  s.name = 'Spree Demo Site'
6
- s.url = 'example.com'
5
+ s.code = 'spree'
6
+ s.url = Rails.application.routes.default_url_options[:host] || 'demo.spreecommerce.org'
7
7
  s.mail_from_address = 'spree@example.com'
8
8
  s.default_currency = 'USD'
9
+ s.seo_title = 'Spree Commerce Demo Shop'
10
+ s.meta_description = 'Spree Commerce is an open source Ecommerce framework decision makers want, developers enjoy.'
11
+ s.facebook = 'spreecommerce'
12
+ s.twitter = 'spreecommerce'
13
+ s.instagram = 'spreecommerce'
9
14
  end.save!
10
15
  end
@@ -6,7 +6,7 @@ class CreateStoreFromPreferences < ActiveRecord::Migration[4.2]
6
6
  false
7
7
  end
8
8
  end
9
-
9
+
10
10
  preference_store = Spree::Preferences::Store.instance
11
11
  if store = Spree::Store.where(default: true).first
12
12
  store.meta_description = preference_store.get('spree/app_configuration/default_meta_description') {}
@@ -26,10 +26,14 @@ class CreateStoreFromPreferences < ActiveRecord::Migration[4.2]
26
26
  'spree@example.com'
27
27
  end
28
28
 
29
- s.meta_description = preference_store.get('spree/app_configuration/default_meta_description') {}
29
+ s.meta_description = preference_store.get('spree/app_configuration/default_meta_description') do
30
+ 'Spree Commerce is an open source Ecommerce framework decision makers want, developers enjoy.'
31
+ end
30
32
  s.meta_keywords = preference_store.get('spree/app_configuration/default_meta_keywords') {}
31
- s.seo_title = preference_store.get('spree/app_configuration/default_seo_title') {}
32
- s.default_currency = preference_store.get('spree/app_configuration/currency') {}
33
+ s.seo_title = preference_store.get('spree/app_configuration/default_seo_title') do
34
+ 'Spree Commerce Demo Shop'
35
+ end
36
+ s.default_currency = preference_store.get('spree/app_configuration/currency') { 'USD' }
33
37
  s.code = 'spree'
34
38
  end.save!
35
39
  end
@@ -0,0 +1,7 @@
1
+ class AddStoreIdToPaymentMethods < ActiveRecord::Migration[5.2]
2
+ def change
3
+ unless column_exists?(:spree_payment_methods, :store_id)
4
+ add_reference :spree_payment_methods, :store, references: :spree_stores, index: true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class AddDeafultValueForStoreDefaultCurrency < ActiveRecord::Migration[6.0]
2
+ def change
3
+ Spree::Store.where(default_currency: nil).update_all(default_currency: Spree::Config[:currency])
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class AddSocialToSpreeStores < ActiveRecord::Migration[6.0]
2
+ def change
3
+ add_column :spree_stores, :facebook, :string
4
+ add_column :spree_stores, :twitter, :string
5
+ add_column :spree_stores, :instagram, :string
6
+ end
7
+ end
@@ -57,6 +57,7 @@ module Spree
57
57
  template 'rails/test.rb', "#{dummy_path}/config/environments/test.rb", force: true
58
58
  template 'rails/script/rails', "#{dummy_path}/spec/dummy/script/rails", force: true
59
59
  template 'initializers/devise.rb', "#{dummy_path}/config/initializers/devise.rb", force: true
60
+ template 'initializers/bullet.rb', "#{dummy_path}/config/initializers/bullet.rb", force: true
60
61
  end
61
62
 
62
63
  def test_dummy_inject_extension_requirements
@@ -137,7 +138,7 @@ end
137
138
  end
138
139
 
139
140
  def gemfile_path
140
- core_gems = ['spree/core', 'spree/api', 'spree/backend', 'spree/frontend', 'spree/sample']
141
+ core_gems = ['spree/core', 'spree/api', 'spree/backend', 'spree/frontend']
141
142
 
142
143
  if core_gems.include?(lib_name)
143
144
  '../../../../../Gemfile'
@@ -0,0 +1,5 @@
1
+ if Rails.env.development? && defined?(Bullet)
2
+ Bullet.enable = true
3
+ Bullet.rails_logger = true
4
+ Bullet.stacktrace_includes = [ 'spree_core', 'spree_frontend', 'spree_api', 'spree_backend' ]
5
+ end
@@ -10,7 +10,7 @@ module Spree
10
10
  class_option :migrate, type: :boolean, default: true, banner: 'Run Spree migrations'
11
11
  class_option :seed, type: :boolean, default: true, banner: 'load seed data (migrations must be run)'
12
12
  class_option :sample, type: :boolean, default: true, banner: 'load sample data (migrations must be run)'
13
- class_option :copy_views, type: :boolean, default: true, banner: 'copy frontend views from spree to your application for easy customization'
13
+ class_option :copy_storefront, type: :boolean, default: true, banner: 'copy storefront from spree frontend to your application for easy customization'
14
14
  class_option :auto_accept, type: :boolean
15
15
  class_option :user_class, type: :string
16
16
  class_option :admin_email, type: :string
@@ -30,7 +30,7 @@ module Spree
30
30
  @run_migrations = options[:migrate]
31
31
  @load_seed_data = options[:seed]
32
32
  @load_sample_data = options[:sample]
33
- @copy_views = options[:copy_views]
33
+ @copy_storefront = options[:copy_storefront]
34
34
 
35
35
  unless @run_migrations
36
36
  @load_seed_data = false
@@ -40,6 +40,11 @@ module Spree
40
40
 
41
41
  def add_files
42
42
  template 'config/initializers/spree.rb', 'config/initializers/spree.rb'
43
+
44
+ if Spree::Core::Engine.frontend_available? || Rails.env.test?
45
+ template 'config/initializers/spree_storefront.rb', 'config/initializers/spree_storefront.rb'
46
+ template 'config/spree_storefront.yml', 'config/spree_storefront.yml'
47
+ end
43
48
  end
44
49
 
45
50
  def additional_tweaks
@@ -54,6 +59,9 @@ module Spree
54
59
  Disallow: /account
55
60
  Disallow: /api
56
61
  Disallow: /password
62
+ Disallow: /api_tokens
63
+ Disallow: /cart_link
64
+ Disallow: /account_link
57
65
  ROBOTS
58
66
  end
59
67
 
@@ -83,9 +91,9 @@ module Spree
83
91
  empty_directory 'app/overrides'
84
92
  end
85
93
 
86
- def copy_views
87
- if @copy_views && Spree::Core::Engine.frontend_available?
88
- generate 'spree:frontend:copy_views'
94
+ def copy_storefront
95
+ if @copy_storefront && Spree::Core::Engine.frontend_available?
96
+ generate 'spree:frontend:copy_storefront'
89
97
  end
90
98
  end
91
99
 
@@ -26,6 +26,5 @@ Spree.dependencies do |dependencies|
26
26
  # dependencies.cart_add_item_service = 'MyNewAwesomeService'
27
27
  end
28
28
 
29
- # Spree::Api::Dependencies.storefront_cart_serializer = 'MyRailsApp::CartSerializer'
30
29
 
31
30
  Spree.user_class = <%= (options[:user_class].blank? ? 'Spree::LegacyUser' : options[:user_class]).inspect %>
@@ -0,0 +1 @@
1
+ SpreeStorefrontConfig = YAML.load_file(Rails.root.join('config', 'spree_storefront.yml')).with_indifferent_access
@@ -0,0 +1,67 @@
1
+ default:
2
+ navigation:
3
+ - title: Women
4
+ subtitle: Categories
5
+ url: /t/women
6
+ items:
7
+ - :title: Skirts
8
+ :url: /t/women/skirts
9
+ - :title: Dresses
10
+ :url: /t/women/dresses
11
+ - :title: Shirts and Blouses
12
+ :url: /t/women/shirts-and-blouses
13
+ - :title: Sweaters
14
+ :url: /t/women/sweaters
15
+ - :title: Tops and T-shirts
16
+ :url: /t/women/tops-and-t-shirts
17
+ - :title: Jackets and Coats
18
+ :url: /t/women/jackets-and-coats
19
+ promo_banners:
20
+ - subtitle: New collection
21
+ title: Summer 2019
22
+ url: /t/summer-collection
23
+ image: 'meganav/promo_banner_left-first-category.jpg'
24
+ - subtitle: Special Offers
25
+ title: Get up to 30% off
26
+ url: /t/special-offers
27
+ image: 'meganav/promo_banner_right-first-category.jpg'
28
+ - title: Men
29
+ subtitle: Categories
30
+ url: /t/men
31
+ items:
32
+ - :title: Shirts
33
+ :url: /t/men/shirts
34
+ - :title: T-shirts
35
+ :url: /t/men/t-shirts
36
+ - :title: Sweaters
37
+ :url: /t/men/sweaters
38
+ - :title: Jackets and Coats
39
+ :url: /t/men/jackets-and-coats
40
+ promo_banners:
41
+ - subtitle: New collection
42
+ title: Summer 2019
43
+ url: /t/summer-collection
44
+ image: 'meganav/promo_banner_left-second-category.jpg'
45
+ - subtitle: Special Offers
46
+ title: Get up to 30% off
47
+ url: /t/special-offers
48
+ image: 'meganav/promo_banner_right-second-category.jpg'
49
+ - title: Sportswear
50
+ subtitle: Categories
51
+ url: /t/sportswear
52
+ items:
53
+ - :title: Tops
54
+ :url: /t/sportswear/tops
55
+ - :title: Sweatshirts
56
+ :url: /t/sportswear/sweatshirts
57
+ - :title: Pants
58
+ :url: /t/sportswear/pants
59
+ promo_banners:
60
+ - subtitle: New collection
61
+ title: Summer 2019
62
+ url: /t/summer-collection
63
+ image: 'meganav/promo_banner_left-third-category.jpg'
64
+ - subtitle: Special Offers
65
+ title: Get up to 30% off
66
+ url: /t/special-offers
67
+ image: 'meganav/promo_banner_right-third-category.jpg'
data/lib/spree/core.rb CHANGED
@@ -93,7 +93,6 @@ require 'spree/money'
93
93
  require 'spree/permitted_attributes'
94
94
  require 'spree/service_module'
95
95
  require 'spree/dependencies_helper'
96
- require 'spree/database_type_utilities'
97
96
 
98
97
  require 'spree/core/importer'
99
98
  require 'spree/core/query_filters'
@@ -5,8 +5,6 @@ module Spree
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- before_action :set_current_order
9
-
10
8
  helper_method :current_order
11
9
  helper_method :simple_current_order
12
10
  end
@@ -28,6 +26,7 @@ module Spree
28
26
  # The current incomplete order from the token for use in cart and during checkout
29
27
  def current_order(options = {})
30
28
  options[:create_order_if_necessary] ||= false
29
+ options[:includes] ||= true
31
30
 
32
31
  if @current_order
33
32
  @current_order.last_ip_address = ip_address
@@ -66,8 +65,8 @@ module Spree
66
65
 
67
66
  private
68
67
 
69
- def last_incomplete_order
70
- @last_incomplete_order ||= try_spree_current_user.last_incomplete_spree_order(current_store)
68
+ def last_incomplete_order(includes = {})
69
+ @last_incomplete_order ||= try_spree_current_user.last_incomplete_spree_order(current_store, includes: includes)
71
70
  end
72
71
 
73
72
  def current_order_params
@@ -77,8 +76,15 @@ module Spree
77
76
  def find_order_by_token_or_user(options = {}, with_adjustments = false)
78
77
  options[:lock] ||= false
79
78
 
79
+ includes = if options[:includes]
80
+ { line_items: [variant: [:images, :option_values, :product]] }
81
+ else
82
+ {}
83
+ end
84
+
80
85
  # Find any incomplete orders for the token
81
- incomplete_orders = Spree::Order.incomplete.includes(line_items: [variant: [:images, :option_values, :product]])
86
+ incomplete_orders = Spree::Order.incomplete.includes(includes)
87
+
82
88
  token_order_params = current_order_params.except(:user_id)
83
89
  order = if with_adjustments
84
90
  incomplete_orders.includes(:adjustments).lock(options[:lock]).find_by(token_order_params)
@@ -87,7 +93,7 @@ module Spree
87
93
  end
88
94
 
89
95
  # Find any incomplete orders for the current user
90
- order = last_incomplete_order if order.nil? && try_spree_current_user
96
+ order = last_incomplete_order(includes) if order.nil? && try_spree_current_user
91
97
 
92
98
  order
93
99
  end
@@ -11,7 +11,7 @@ module Spree
11
11
  end
12
12
 
13
13
  def current_currency
14
- Spree::Config[:currency]
14
+ current_store.default_currency
15
15
  end
16
16
 
17
17
  def current_store
@@ -43,7 +43,7 @@ module Spree
43
43
  private
44
44
 
45
45
  def current_tax_zone
46
- @current_tax_zone ||= current_order.try(:tax_zone) || Spree::Zone.default_tax
46
+ @current_tax_zone ||= @current_order&.tax_zone || Spree::Zone.default_tax
47
47
  end
48
48
  end
49
49
  end
@@ -13,7 +13,7 @@ module Spree
13
13
  end
14
14
 
15
15
  def retrieve_products
16
- @products = get_base_scope
16
+ @products = extended_base_scope&.available
17
17
  curr_page = page || 1
18
18
 
19
19
  unless Spree::Config.show_products_without_price
@@ -33,34 +33,37 @@ module Spree
33
33
 
34
34
  protected
35
35
 
36
- def get_base_scope
36
+ def extended_base_scope
37
37
  base_scope = Spree::Product.spree_base_scopes.active
38
- base_scope = base_scope.in_taxon(taxon) unless taxon.blank?
39
38
  base_scope = get_products_conditions_for(base_scope, keywords)
39
+ base_scope = Spree::Products::Find.new(
40
+ scope: base_scope,
41
+ params: {
42
+ filter: {
43
+ price: price,
44
+ option_value_ids: option_value_ids,
45
+ taxons: taxon&.id
46
+ },
47
+ sort_by: sort_by
48
+ },
49
+ current_currency: current_currency
50
+ ).execute
40
51
  base_scope = add_search_scopes(base_scope)
41
52
  base_scope = add_eagerload_scopes(base_scope)
42
53
  base_scope
43
54
  end
44
55
 
45
56
  def add_eagerload_scopes(scope)
46
- # TL;DR Switch from `preload` to `includes` as soon as Rails starts honoring
47
- # `order` clauses on `has_many` associations when a `where` constraint
48
- # affecting a joined table is present (see
49
- # https://github.com/rails/rails/issues/6769).
50
- #
51
- # Ideally this would use `includes` instead of `preload` calls, leaving it
52
- # up to Rails whether associated objects should be fetched in one big join
53
- # or multiple independent queries. However as of Rails 4.1.8 any `order`
54
- # defined on `has_many` associations are ignored when Rails builds a join
55
- # query.
56
- #
57
- # Would we use `includes` in this particular case, Rails would do
58
- # separate queries most of the time but opt for a join as soon as any
59
- # `where` constraints affecting joined tables are added to the search;
60
- # which is the case as soon as a taxon is added to the base scope.
61
- scope = scope.preload(:tax_category)
62
- scope = scope.preload(master: :prices)
63
- scope = scope.preload(master: :images) if include_images
57
+ scope = scope.includes(
58
+ :tax_category,
59
+ variants: [
60
+ { images: { attachment_attachment: :blob } }
61
+ ],
62
+ master: [
63
+ :prices,
64
+ { images: { attachment_attachment: :blob } }
65
+ ]
66
+ )
64
67
  scope
65
68
  end
66
69
 
@@ -68,6 +71,7 @@ module Spree
68
71
  if search.is_a?(ActionController::Parameters)
69
72
  search.each do |name, scope_attribute|
70
73
  scope_name = name.to_sym
74
+
71
75
  base_scope = if base_scope.respond_to?(:search_scopes) && base_scope.search_scopes.include?(scope_name.to_sym)
72
76
  base_scope.send(scope_name, *scope_attribute)
73
77
  else
@@ -81,15 +85,48 @@ module Spree
81
85
  # method should return new scope based on base_scope
82
86
  def get_products_conditions_for(base_scope, query)
83
87
  unless query.blank?
84
- base_scope = base_scope.like_any([:name, :description], query.split)
88
+ base_scope = base_scope.like_any([:name, :description], [query])
89
+ end
90
+ base_scope
91
+ end
92
+
93
+ def get_products_option_values_conditions(base_scope, option_value_ids)
94
+ unless option_value_ids.blank?
95
+ base_scope = base_scope.joins(variants: :option_values).where(spree_option_values: { id: option_value_ids })
85
96
  end
86
97
  base_scope
87
98
  end
88
99
 
100
+ def get_price_range(price_param)
101
+ return if price_param.blank?
102
+
103
+ less_than_string = I18n.t('activerecord.attributes.spree/product.less_than')
104
+
105
+ if price_param.include? less_than_string
106
+ low_price = 0
107
+ high_price = Monetize.parse(price_param.remove("#{less_than_string} ")).to_i
108
+ else
109
+ low_price, high_price = Monetize.parse_collection(price_param).map(&:to_i)
110
+ end
111
+
112
+ "#{low_price},#{high_price}"
113
+ end
114
+
115
+ def build_option_value_ids(params)
116
+ filter_params = Spree::OptionType.all.map(&:filter_param)
117
+
118
+ filter_params.reduce([]) do |acc, filter_param|
119
+ acc + params[filter_param].to_s.split(',')
120
+ end
121
+ end
122
+
89
123
  def prepare(params)
90
124
  @properties[:taxon] = params[:taxon].blank? ? nil : Spree::Taxon.find(params[:taxon])
91
125
  @properties[:keywords] = params[:keywords]
126
+ @properties[:option_value_ids] = build_option_value_ids(params)
127
+ @properties[:price] = get_price_range(params[:price])
92
128
  @properties[:search] = params[:search]
129
+ @properties[:sort_by] = params[:sort_by] || 'default'
93
130
  @properties[:include_images] = params[:include_images]
94
131
 
95
132
  per_page = params[:per_page].to_i
@@ -1,7 +1,5 @@
1
1
  module Spree
2
- VERSION = '4.0.7'.freeze
3
-
4
2
  def self.version
5
- VERSION
3
+ '4.1.0.rc1'
6
4
  end
7
5
  end
data/lib/spree/money.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'money'
2
2
 
3
3
  Money.locale_backend = :i18n
4
+ Money.rounding_mode = BigDecimal::ROUND_HALF_UP
4
5
 
5
6
  module Spree
6
7
  class Money
@@ -18,6 +19,7 @@ module Spree
18
19
  delegate :cents, :currency, to: :money
19
20
 
20
21
  def initialize(amount, options = {})
22
+ use_default_currency
21
23
  @money = Monetize.parse([amount, (options[:currency] || Spree::Config[:currency])].join)
22
24
  @options = Spree::Money.default_formatting_rules.merge(options)
23
25
  end
@@ -27,7 +29,7 @@ module Spree
27
29
  end
28
30
 
29
31
  def to_s
30
- money.format(options)
32
+ money&.format(options)
31
33
  end
32
34
 
33
35
  # 1) prevent blank, breaking spaces
@@ -62,6 +64,11 @@ module Spree
62
64
  money == obj.money
63
65
  end
64
66
 
67
+ def use_default_currency
68
+ currency = Spree::Store.default.default_currency || Spree::Config[:currency]
69
+ ::Money.default_currency = currency
70
+ end
71
+
65
72
  private
66
73
 
67
74
  attr_reader :options