spree_core 4.0.7 → 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.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