spree_core 4.3.0.rc1 → 4.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/finders/spree/products/find.rb +26 -2
- data/app/finders/spree/taxons/find.rb +22 -6
- data/app/helpers/spree/base_helper.rb +7 -5
- data/app/models/concerns/spree/display_money.rb +6 -2
- data/app/models/concerns/spree/image_methods.rb +24 -0
- data/app/models/concerns/spree/product_scopes.rb +12 -0
- data/app/models/concerns/spree/single_store_resource.rb +10 -0
- data/app/models/concerns/spree/user_methods.rb +9 -8
- data/app/models/concerns/spree/user_reporting.rb +35 -10
- data/app/models/concerns/spree/user_roles.rb +25 -0
- data/app/models/spree/app_dependencies.rb +3 -1
- data/app/models/spree/cms/sections/featured_article.rb +0 -7
- data/app/models/spree/cms/sections/hero_image.rb +0 -9
- data/app/models/spree/cms/sections/image_gallery.rb +2 -2
- data/app/models/spree/cms/sections/side_by_side_images.rb +2 -2
- data/app/models/spree/cms_section.rb +12 -0
- data/app/models/spree/gateway/bogus.rb +6 -4
- data/app/models/spree/image.rb +5 -24
- data/app/models/spree/payment_method.rb +12 -0
- data/app/models/spree/product.rb +10 -8
- data/app/models/spree/property.rb +1 -1
- data/app/models/spree/stock_location.rb +9 -0
- data/app/models/spree/store.rb +2 -2
- data/app/models/spree/taxon.rb +1 -0
- data/app/models/spree/taxon_image.rb +1 -0
- data/app/models/spree/variant.rb +9 -3
- data/app/presenters/spree/filters/options_presenter.rb +20 -0
- data/app/presenters/spree/filters/property_presenter.rb +20 -0
- data/app/services/spree/cart/associate.rb +16 -0
- data/app/services/spree/cart/change_currency.rb +27 -0
- data/app/sorters/spree/base_sorter.rb +23 -11
- data/app/sorters/spree/products/sort.rb +23 -7
- data/config/locales/en.yml +11 -1
- data/db/migrate/20210527094055_create_spree_products_stores.rb +15 -8
- data/lib/generators/spree/dummy/dummy_generator.rb +1 -1
- data/lib/generators/spree/dummy/templates/rails/test.rb +2 -0
- data/lib/spree/core/controller_helpers/store.rb +14 -0
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/permitted_attributes.rb +7 -0
- data/lib/spree/testing_support/factories/product_factory.rb +6 -0
- data/lib/spree/testing_support/locale_helpers.rb +1 -1
- data/lib/spree/testing_support/rspec_retry_config.rb +5 -0
- data/spree_core.gemspec +1 -1
- metadata +10 -7
- data/app/views/spree/shared/_purchased_items_table.text.erb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9362a52bbabd7b09ffc2bc0271bffc4a2d11bc311d7356b56db0271c79f0740
|
4
|
+
data.tar.gz: 41a19d295a5dad9f3b2dadfe07fe73210e5a57139cc82eeb170d9d2d6e143910
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b75ef727652e108dd4c34cf10bf2ab1d82abff4c9283ce2ee3c00078b328dbbcdcc38d729f7a1fa75d7a773470e48e5b3ce02d36d6cd33fbed5f8906dadfa944
|
7
|
+
data.tar.gz: eeaaf0d1aaa49aaaafd30b55ddc04e50ddcdc922ecd7779e9b98283ca5c8ac4e5fd899c73d770e8cbaa93474e25b3af40e0747612cb761e825afeb36988d2254
|
@@ -27,6 +27,9 @@ module Spree
|
|
27
27
|
@deleted = params.dig(:filter, :show_deleted)
|
28
28
|
@discontinued = params.dig(:filter, :show_discontinued)
|
29
29
|
@properties = params.dig(:filter, :properties)
|
30
|
+
@in_stock = params.dig(:filter, :in_stock)
|
31
|
+
@backorderable = params.dig(:filter, :backorderable)
|
32
|
+
@purchasable = params.dig(:filter, :purchasable)
|
30
33
|
end
|
31
34
|
|
32
35
|
def execute
|
@@ -42,6 +45,9 @@ module Spree
|
|
42
45
|
products = by_properties(products)
|
43
46
|
products = include_deleted(products)
|
44
47
|
products = include_discontinued(products)
|
48
|
+
products = show_only_stock(products)
|
49
|
+
products = show_only_backorderable(products)
|
50
|
+
products = show_only_purchasable(products)
|
45
51
|
products = ordered(products)
|
46
52
|
|
47
53
|
products.distinct
|
@@ -49,8 +55,8 @@ module Spree
|
|
49
55
|
|
50
56
|
private
|
51
57
|
|
52
|
-
attr_reader :ids, :skus, :price, :currency, :taxons, :concat_taxons, :name, :options,
|
53
|
-
:
|
58
|
+
attr_reader :ids, :skus, :price, :currency, :taxons, :concat_taxons, :name, :options, :option_value_ids, :scope,
|
59
|
+
:sort_by, :deleted, :discontinued, :properties, :store, :in_stock, :backorderable, :purchasable
|
54
60
|
|
55
61
|
def ids?
|
56
62
|
ids.present?
|
@@ -231,6 +237,24 @@ module Spree
|
|
231
237
|
discontinued ? products : products.active(currency)
|
232
238
|
end
|
233
239
|
|
240
|
+
def show_only_stock(products)
|
241
|
+
return products unless in_stock.to_s == 'true'
|
242
|
+
|
243
|
+
products.in_stock
|
244
|
+
end
|
245
|
+
|
246
|
+
def show_only_backorderable(products)
|
247
|
+
return products unless backorderable.to_s == 'true'
|
248
|
+
|
249
|
+
products.backorderable
|
250
|
+
end
|
251
|
+
|
252
|
+
def show_only_purchasable(products)
|
253
|
+
return products unless purchasable.to_s == 'true'
|
254
|
+
|
255
|
+
products.in_stock_or_backorderable
|
256
|
+
end
|
257
|
+
|
234
258
|
def map_prices(prices)
|
235
259
|
prices.map do |price|
|
236
260
|
price == 'Infinity' ? Float::INFINITY : price.to_f
|
@@ -3,16 +3,18 @@ module Spree
|
|
3
3
|
class Find
|
4
4
|
def initialize(scope:, params:)
|
5
5
|
@scope = scope
|
6
|
-
@ids
|
7
|
-
@parent
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
6
|
+
@ids = String(params.dig(:filter, :ids)).split(',')
|
7
|
+
@parent = params.dig(:filter, :parent_id)
|
8
|
+
@parent_permalink = params.dig(:filter, :parent_permalink)
|
9
|
+
@taxonomy = params.dig(:filter, :taxonomy_id)
|
10
|
+
@name = params.dig(:filter, :name)
|
11
|
+
@roots = params.dig(:filter, :roots)
|
11
12
|
end
|
12
13
|
|
13
14
|
def execute
|
14
15
|
taxons = by_ids(scope)
|
15
16
|
taxons = by_parent(taxons)
|
17
|
+
taxons = by_parent_permalink(taxons)
|
16
18
|
taxons = by_taxonomy(taxons)
|
17
19
|
taxons = by_roots(taxons)
|
18
20
|
taxons = by_name(taxons)
|
@@ -22,7 +24,7 @@ module Spree
|
|
22
24
|
|
23
25
|
private
|
24
26
|
|
25
|
-
attr_reader :ids, :parent, :taxonomy, :roots, :name, :scope
|
27
|
+
attr_reader :ids, :parent, :parent_permalink, :taxonomy, :roots, :name, :scope
|
26
28
|
|
27
29
|
def ids?
|
28
30
|
ids.present?
|
@@ -32,6 +34,10 @@ module Spree
|
|
32
34
|
parent.present?
|
33
35
|
end
|
34
36
|
|
37
|
+
def parent_permalink?
|
38
|
+
parent_permalink.present?
|
39
|
+
end
|
40
|
+
|
35
41
|
def taxonomy?
|
36
42
|
taxonomy.present?
|
37
43
|
end
|
@@ -60,6 +66,16 @@ module Spree
|
|
60
66
|
taxons.where(parent_id: parent)
|
61
67
|
end
|
62
68
|
|
69
|
+
def by_parent_permalink(taxons)
|
70
|
+
return taxons unless parent_permalink?
|
71
|
+
|
72
|
+
if Rails::VERSION::STRING >= '6.1'
|
73
|
+
taxons.joins(:parent).where(parent: { permalink: parent_permalink })
|
74
|
+
else
|
75
|
+
taxons.joins("INNER JOIN #{Spree::Taxon.table_name} AS parent_taxon ON parent_taxon.id = #{Spree::Taxon.table_name}.parent_id").where(["parent_taxon.permalink = ?", parent_permalink])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
63
79
|
def by_taxonomy(taxons)
|
64
80
|
return taxons unless taxonomy?
|
65
81
|
|
@@ -246,11 +246,13 @@ module Spree
|
|
246
246
|
options = options.first || {}
|
247
247
|
options[:alt] ||= product.name
|
248
248
|
image_path = default_image_for_product_or_variant(product)
|
249
|
-
if image_path.present?
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
249
|
+
img = if image_path.present?
|
250
|
+
create_product_image_tag image_path, product, options, style
|
251
|
+
else
|
252
|
+
inline_svg_tag "noimage/backend-missing-image.svg", class: "noimage", size: "60%*60%"
|
253
|
+
end
|
254
|
+
|
255
|
+
content_tag(:div, img, class: "admin-product-image-container #{style}-img")
|
254
256
|
end
|
255
257
|
end
|
256
258
|
|
@@ -17,13 +17,17 @@ module Spree
|
|
17
17
|
# Decorate a method, but with some additional options
|
18
18
|
# extend Spree::DisplayMoney
|
19
19
|
# money_methods tax_amount: { currency: "CAD", no_cents: true }, :price
|
20
|
+
# Use generated method with the same arguments as in wrapped method
|
21
|
+
# def tax_amount(order, country)
|
22
|
+
# display_tax_amount(order, country)
|
20
23
|
def money_methods(*args)
|
21
24
|
args.each do |money_method|
|
22
25
|
money_method = { money_method => {} } unless money_method.is_a? Hash
|
23
26
|
money_method.each do |method_name, opts|
|
24
|
-
define_method("display_#{method_name}") do
|
27
|
+
define_method("display_#{method_name}") do |**args_list|
|
25
28
|
default_opts = respond_to?(:currency) ? { currency: currency } : {}
|
26
|
-
|
29
|
+
|
30
|
+
Spree::Money.new(send(method_name, **args_list), default_opts.merge(opts).merge(args_list.slice(:currency)))
|
27
31
|
end
|
28
32
|
end
|
29
33
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Spree
|
2
|
+
module ImageMethods
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def generate_url(size:, gravity: 'center', quality: 80, background: 'show')
|
6
|
+
return if size.blank?
|
7
|
+
size = size.gsub(/\s+/, '')
|
8
|
+
|
9
|
+
return unless size.match(/(\d+)x(\d+)/)
|
10
|
+
|
11
|
+
polymorphic_path(attachment.variant(
|
12
|
+
gravity: gravity,
|
13
|
+
resize: size,
|
14
|
+
extent: size,
|
15
|
+
background: background,
|
16
|
+
quality: quality.to_i
|
17
|
+
), only_path: true)
|
18
|
+
end
|
19
|
+
|
20
|
+
def original_url
|
21
|
+
polymorphic_path(attachment, only_path: true)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -62,6 +62,18 @@ module Spree
|
|
62
62
|
where("#{price_table_name}.amount >= ?", price)
|
63
63
|
end
|
64
64
|
|
65
|
+
add_search_scope :in_stock do
|
66
|
+
joins(:variants_including_master).merge(Spree::Variant.in_stock)
|
67
|
+
end
|
68
|
+
|
69
|
+
add_search_scope :backorderable do
|
70
|
+
joins(:variants_including_master).merge(Spree::Variant.backorderable)
|
71
|
+
end
|
72
|
+
|
73
|
+
add_search_scope :in_stock_or_backorderable do
|
74
|
+
joins(:variants_including_master).merge(Spree::Variant.in_stock_or_backorderable)
|
75
|
+
end
|
76
|
+
|
65
77
|
# This scope selects products in taxon AND all its descendants
|
66
78
|
# If you need products only within one taxon use
|
67
79
|
#
|
@@ -3,7 +3,17 @@ module Spree
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
+
validate :ensure_store_association_is_not_changed
|
7
|
+
|
6
8
|
scope :for_store, ->(store) { where(store_id: store.id) }
|
7
9
|
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def ensure_store_association_is_not_changed
|
14
|
+
if store_id_changed? && persisted?
|
15
|
+
errors.add(:store, Spree.t('errors.messages.store_association_can_not_be_changed'))
|
16
|
+
end
|
17
|
+
end
|
8
18
|
end
|
9
19
|
end
|
@@ -4,6 +4,7 @@ module Spree
|
|
4
4
|
|
5
5
|
include Spree::UserPaymentSource
|
6
6
|
include Spree::UserReporting
|
7
|
+
include Spree::UserRoles
|
7
8
|
include Spree::RansackableAttributes
|
8
9
|
|
9
10
|
included do
|
@@ -15,9 +16,6 @@ module Spree
|
|
15
16
|
|
16
17
|
attr_accessor :use_billing
|
17
18
|
|
18
|
-
has_many :role_users, class_name: 'Spree::RoleUser', foreign_key: :user_id, dependent: :destroy
|
19
|
-
has_many :spree_roles, through: :role_users, class_name: 'Spree::Role', source: :role
|
20
|
-
|
21
19
|
has_many :promotion_rule_users, class_name: 'Spree::PromotionRuleUser', foreign_key: :user_id, dependent: :destroy
|
22
20
|
has_many :promotion_rules, through: :promotion_rule_users, class_name: 'Spree::PromotionRule'
|
23
21
|
|
@@ -47,11 +45,6 @@ module Spree
|
|
47
45
|
end
|
48
46
|
end
|
49
47
|
|
50
|
-
# has_spree_role? simply needs to return true or false whether a user has a role or not.
|
51
|
-
def has_spree_role?(role_in_question)
|
52
|
-
spree_roles.any? { |role| role.name == role_in_question.to_s }
|
53
|
-
end
|
54
|
-
|
55
48
|
def last_incomplete_spree_order(store, options = {})
|
56
49
|
orders.where(store: store).incomplete.
|
57
50
|
includes(options[:includes]).
|
@@ -65,6 +58,14 @@ module Spree
|
|
65
58
|
store_credits.for_store(store).where(currency: currency).reload.to_a.sum(&:amount_remaining)
|
66
59
|
end
|
67
60
|
|
61
|
+
def available_store_credits(store)
|
62
|
+
store ||= Store.default
|
63
|
+
|
64
|
+
store_credits.for_store(store).pluck(:currency).uniq.each_with_object([]) do |currency, arr|
|
65
|
+
arr << Spree::Money.new(total_available_store_credit(currency, store), currency: currency)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
68
69
|
private
|
69
70
|
|
70
71
|
def check_completed_orders
|
@@ -3,20 +3,45 @@ module Spree
|
|
3
3
|
extend DisplayMoney
|
4
4
|
money_methods :lifetime_value, :average_order_value
|
5
5
|
|
6
|
-
def
|
7
|
-
|
6
|
+
def report_values_for(report_name, store)
|
7
|
+
store ||= Store.default
|
8
|
+
|
9
|
+
completed_orders(store).pluck(:currency).uniq.each_with_object([]) do |currency, arr|
|
10
|
+
arr << send("display_#{report_name}", store: store, currency: currency)
|
11
|
+
end
|
8
12
|
end
|
9
13
|
|
10
|
-
def
|
11
|
-
|
14
|
+
def lifetime_value(**args)
|
15
|
+
order_calculate(operation: :sum,
|
16
|
+
column: :total,
|
17
|
+
**args)
|
12
18
|
end
|
13
19
|
|
14
|
-
def average_order_value
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
def average_order_value(**args)
|
21
|
+
order_calculate(operation: :average,
|
22
|
+
column: :total,
|
23
|
+
**args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def order_count(store = nil)
|
27
|
+
store ||= Store.default
|
28
|
+
order_calculate(store: store,
|
29
|
+
currency: store.supported_currencies.split(','),
|
30
|
+
operation: :count,
|
31
|
+
column: :all)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def order_calculate(operation:, column:, store: nil, currency: nil)
|
37
|
+
store ||= Store.default
|
38
|
+
currency ||= store.default_currency
|
39
|
+
|
40
|
+
completed_orders(store).where(currency: currency).calculate(operation, column) || BigDecimal('0.00')
|
41
|
+
end
|
42
|
+
|
43
|
+
def completed_orders(store)
|
44
|
+
orders.for_store(store).complete
|
20
45
|
end
|
21
46
|
end
|
22
47
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Spree
|
2
|
+
module UserRoles
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
has_many :role_users, class_name: 'Spree::RoleUser', foreign_key: :user_id, dependent: :destroy
|
7
|
+
has_many :spree_roles, through: :role_users, class_name: 'Spree::Role', source: :role
|
8
|
+
|
9
|
+
scope :admin, -> { joins(:spree_roles).where(Spree::Role.table_name => { name: 'admin' }) }
|
10
|
+
|
11
|
+
# has_spree_role? simply needs to return true or false whether a user has a role or not.
|
12
|
+
def has_spree_role?(role_name)
|
13
|
+
spree_roles.exists?(name: role_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.admin_created?
|
17
|
+
admin.exists?
|
18
|
+
end
|
19
|
+
|
20
|
+
def admin?
|
21
|
+
has_spree_role?('admin')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -13,7 +13,7 @@ module Spree
|
|
13
13
|
:products_finder, :taxon_finder, :line_item_by_variant_finder, :cart_estimate_shipping_rates_service,
|
14
14
|
:account_create_address_service, :account_update_address_service, :account_create_service, :account_update_service,
|
15
15
|
:address_finder, :collection_sorter, :error_handler, :current_store_finder, :cart_empty_service, :cart_destroy_service,
|
16
|
-
:classification_reposition_service, :credit_cards_destroy_service
|
16
|
+
:classification_reposition_service, :credit_cards_destroy_service, :cart_associate_service, :cart_change_currency_service
|
17
17
|
].freeze
|
18
18
|
|
19
19
|
attr_accessor *INJECTION_POINTS
|
@@ -43,6 +43,8 @@ module Spree
|
|
43
43
|
@cart_estimate_shipping_rates_service = 'Spree::Cart::EstimateShippingRates'
|
44
44
|
@cart_empty_service = 'Spree::Cart::Empty'
|
45
45
|
@cart_destroy_service = 'Spree::Cart::Destroy'
|
46
|
+
@cart_associate_service = 'Spree::Cart::Associate'
|
47
|
+
@cart_change_currency_service = 'Spree::Cart::ChangeCurrency'
|
46
48
|
|
47
49
|
# checkout
|
48
50
|
@checkout_next_service = 'Spree::Checkout::Next'
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Spree::Cms::Sections
|
2
2
|
class FeaturedArticle < Spree::CmsSection
|
3
|
-
before_save :reset_link_attributes
|
4
3
|
after_initialize :default_values
|
5
4
|
|
6
5
|
store :content, accessors: [:title, :subtitle, :button_text, :rte_content], coder: JSON
|
@@ -14,12 +13,6 @@ module Spree::Cms::Sections
|
|
14
13
|
|
15
14
|
private
|
16
15
|
|
17
|
-
def reset_link_attributes
|
18
|
-
if linked_resource_type_changed?
|
19
|
-
self.linked_resource_id = nil
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
16
|
def default_values
|
24
17
|
self.gutters ||= 'No Gutters'
|
25
18
|
self.fit ||= 'Screen'
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Spree::Cms::Sections
|
2
2
|
class HeroImage < Spree::CmsSection
|
3
|
-
before_save :reset_link_attributes
|
4
3
|
after_initialize :default_values
|
5
4
|
|
6
5
|
store :content, accessors: [:title, :button_text], coder: JSON
|
@@ -30,14 +29,6 @@ module Spree::Cms::Sections
|
|
30
29
|
|
31
30
|
private
|
32
31
|
|
33
|
-
def reset_link_attributes
|
34
|
-
if linked_resource_type_changed?
|
35
|
-
return if linked_resource_id_was.nil?
|
36
|
-
|
37
|
-
self.linked_resource_id = nil
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
32
|
def default_values
|
42
33
|
self.gutters ||= 'No Gutters'
|
43
34
|
self.fit ||= 'Screen'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Spree::Cms::Sections
|
2
2
|
class ImageGallery < Spree::CmsSection
|
3
3
|
after_initialize :default_values
|
4
|
-
|
4
|
+
validate :reset_multiple_link_attributes
|
5
5
|
|
6
6
|
LINKED_RESOURCE_TYPE = if Rails::VERSION::STRING < '6.0'
|
7
7
|
['Spree::Taxon'].freeze
|
@@ -70,7 +70,7 @@ module Spree::Cms::Sections
|
|
70
70
|
|
71
71
|
private
|
72
72
|
|
73
|
-
def
|
73
|
+
def reset_multiple_link_attributes
|
74
74
|
return if Rails::VERSION::STRING < '6.0'
|
75
75
|
|
76
76
|
if link_type_one_changed?
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Spree::Cms::Sections
|
2
2
|
class SideBySideImages < Spree::CmsSection
|
3
3
|
after_initialize :default_values
|
4
|
-
|
4
|
+
validate :reset_multiple_link_attributes
|
5
5
|
|
6
6
|
LINKED_RESOURCE_TYPE = if Rails::VERSION::STRING < '6.0'
|
7
7
|
['Spree::Taxon'].freeze
|
@@ -48,7 +48,7 @@ module Spree::Cms::Sections
|
|
48
48
|
|
49
49
|
private
|
50
50
|
|
51
|
-
def
|
51
|
+
def reset_multiple_link_attributes
|
52
52
|
return if Rails::VERSION::STRING < '6.0'
|
53
53
|
|
54
54
|
if link_type_one_changed?
|
@@ -5,6 +5,8 @@ module Spree
|
|
5
5
|
acts_as_list scope: :cms_page
|
6
6
|
belongs_to :cms_page, touch: true
|
7
7
|
|
8
|
+
validate :reset_link_attributes
|
9
|
+
|
8
10
|
IMAGE_COUNT = ['one', 'two', 'three']
|
9
11
|
IMAGE_TYPES = ['image/png', 'image/jpg', 'image/jpeg', 'image/gif'].freeze
|
10
12
|
IMAGE_SIZE = ['sm', 'md', 'lg', 'xl']
|
@@ -53,5 +55,15 @@ module Spree
|
|
53
55
|
def fullscreen?
|
54
56
|
fit == 'Screen'
|
55
57
|
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def reset_link_attributes
|
62
|
+
if linked_resource_type_changed?
|
63
|
+
return if linked_resource_id_was.nil?
|
64
|
+
|
65
|
+
self.linked_resource_id = nil
|
66
|
+
end
|
67
|
+
end
|
56
68
|
end
|
57
69
|
end
|
@@ -9,14 +9,12 @@ module Spree
|
|
9
9
|
|
10
10
|
attr_accessor :test
|
11
11
|
|
12
|
+
preference :dummy_key, :string, default: 'PUBLICKEY123'
|
13
|
+
|
12
14
|
def provider_class
|
13
15
|
self.class
|
14
16
|
end
|
15
17
|
|
16
|
-
def preferences
|
17
|
-
{}
|
18
|
-
end
|
19
|
-
|
20
18
|
def create_profile(payment)
|
21
19
|
return if payment.source.has_payment_profile?
|
22
20
|
|
@@ -88,5 +86,9 @@ module Spree
|
|
88
86
|
end
|
89
87
|
random
|
90
88
|
end
|
89
|
+
|
90
|
+
def public_preference_keys
|
91
|
+
[:dummy_key]
|
92
|
+
end
|
91
93
|
end
|
92
94
|
end
|
data/app/models/spree/image.rb
CHANGED
@@ -2,6 +2,7 @@ module Spree
|
|
2
2
|
class Image < Asset
|
3
3
|
include Configuration::ActiveStorage
|
4
4
|
include Rails.application.routes.url_helpers
|
5
|
+
include ::Spree::ImageMethods
|
5
6
|
|
6
7
|
# In Rails 5.x class constants are being undefined/redefined during the code reloading process
|
7
8
|
# in a rails development environment, after which the actual ruby objects stored in those class constants
|
@@ -15,13 +16,8 @@ module Spree
|
|
15
16
|
width, height = size.chop.split('x')
|
16
17
|
|
17
18
|
{
|
18
|
-
url:
|
19
|
-
|
20
|
-
resize: size,
|
21
|
-
extent: size,
|
22
|
-
background: 'snow2',
|
23
|
-
quality: 80
|
24
|
-
), only_path: true),
|
19
|
+
url: generate_url(size: size),
|
20
|
+
size: size,
|
25
21
|
width: width,
|
26
22
|
height: height
|
27
23
|
}
|
@@ -35,13 +31,7 @@ module Spree
|
|
35
31
|
width, height = size.chop.split('x')
|
36
32
|
|
37
33
|
{
|
38
|
-
url:
|
39
|
-
gravity: 'center',
|
40
|
-
resize: size,
|
41
|
-
extent: size,
|
42
|
-
background: 'snow2',
|
43
|
-
quality: 80
|
44
|
-
), only_path: true),
|
34
|
+
url: generate_url(size: size),
|
45
35
|
size: size,
|
46
36
|
width: width,
|
47
37
|
height: height
|
@@ -59,16 +49,7 @@ module Spree
|
|
59
49
|
end
|
60
50
|
|
61
51
|
def plp_url
|
62
|
-
size
|
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)
|
52
|
+
generate_url(size: self.class.styles[:plp_and_carousel])
|
72
53
|
end
|
73
54
|
end
|
74
55
|
end
|
@@ -87,5 +87,17 @@ module Spree
|
|
87
87
|
|
88
88
|
store_ids.include?(store.id)
|
89
89
|
end
|
90
|
+
|
91
|
+
def public_preferences
|
92
|
+
public_preference_keys.each_with_object({}) do |key, hash|
|
93
|
+
hash[key] = preferences[key]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
|
99
|
+
def public_preference_keys
|
100
|
+
[]
|
101
|
+
end
|
90
102
|
end
|
91
103
|
end
|
data/app/models/spree/product.rb
CHANGED
@@ -142,17 +142,17 @@ module Spree
|
|
142
142
|
|
143
143
|
# Cant use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
|
144
144
|
def purchasable?
|
145
|
-
|
145
|
+
default_variant.purchasable? || variants.any?(&:purchasable?)
|
146
146
|
end
|
147
147
|
|
148
148
|
# Cant use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
|
149
149
|
def in_stock?
|
150
|
-
|
150
|
+
default_variant.in_stock? || variants.any?(&:in_stock?)
|
151
151
|
end
|
152
152
|
|
153
153
|
# Cant use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
|
154
154
|
def backorderable?
|
155
|
-
|
155
|
+
default_variant.backorderable? || variants.any?(&:backorderable?)
|
156
156
|
end
|
157
157
|
|
158
158
|
def find_or_build_master
|
@@ -301,11 +301,13 @@ module Spree
|
|
301
301
|
end
|
302
302
|
|
303
303
|
def total_on_hand
|
304
|
-
@total_on_hand ||=
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
304
|
+
@total_on_hand ||= Rails.cache.fetch(['product-total-on-hand', cache_key_with_version]) do
|
305
|
+
if any_variants_not_track_inventory?
|
306
|
+
Float::INFINITY
|
307
|
+
else
|
308
|
+
stock_items.sum(:count_on_hand)
|
309
|
+
end
|
310
|
+
end
|
309
311
|
end
|
310
312
|
|
311
313
|
# Master variant may be deleted (i.e. when the product is deleted)
|
@@ -18,7 +18,7 @@ module Spree
|
|
18
18
|
after_touch :touch_all_products
|
19
19
|
after_save :ensure_product_properties_have_filter_params
|
20
20
|
|
21
|
-
self.whitelisted_ransackable_attributes = ['presentation']
|
21
|
+
self.whitelisted_ransackable_attributes = ['presentation', 'filterable']
|
22
22
|
|
23
23
|
def uniq_values(product_properties_scope: nil)
|
24
24
|
with_uniq_values_cache_key(product_properties_scope) do
|
@@ -2,6 +2,7 @@ module Spree
|
|
2
2
|
class StockLocation < Spree::Base
|
3
3
|
has_many :shipments
|
4
4
|
has_many :stock_items, dependent: :delete_all, inverse_of: :stock_location
|
5
|
+
has_many :variants, through: :stock_items
|
5
6
|
has_many :stock_movements, through: :stock_items
|
6
7
|
|
7
8
|
belongs_to :state, class_name: 'Spree::State', optional: true
|
@@ -14,6 +15,7 @@ module Spree
|
|
14
15
|
|
15
16
|
after_create :create_stock_items, if: :propagate_all_variants?
|
16
17
|
after_save :ensure_one_default
|
18
|
+
after_update :conditional_touch_records
|
17
19
|
|
18
20
|
def state_text
|
19
21
|
state.try(:abbr) || state.try(:name) || state_name
|
@@ -134,5 +136,12 @@ module Spree
|
|
134
136
|
StockLocation.where(default: true).where.not(id: id).update_all(default: false)
|
135
137
|
end
|
136
138
|
end
|
139
|
+
|
140
|
+
def conditional_touch_records
|
141
|
+
return unless active_changed?
|
142
|
+
|
143
|
+
stock_items.update_all(updated_at: Time.current)
|
144
|
+
variants.update_all(updated_at: Time.current)
|
145
|
+
end
|
137
146
|
end
|
138
147
|
end
|
data/app/models/spree/store.rb
CHANGED
@@ -76,8 +76,8 @@ module Spree
|
|
76
76
|
|
77
77
|
def self.current(url = nil)
|
78
78
|
ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
|
79
|
-
`Spree::Store.current` is deprecated and will be removed in Spree 5
|
80
|
-
Spree::Stores::FindCurrent.new(url: "
|
79
|
+
`Spree::Store.current` is deprecated and will be removed in Spree 5.0
|
80
|
+
Please use `Spree::Stores::FindCurrent.new(url: "https://example.com").execute` instead
|
81
81
|
DEPRECATION
|
82
82
|
Stores::FindCurrent.new(url: url).execute
|
83
83
|
end
|
data/app/models/spree/taxon.rb
CHANGED
@@ -44,6 +44,7 @@ module Spree
|
|
44
44
|
scope :for_store, ->(store) { joins(:taxonomy).where(spree_taxonomies: { store_id: store.id }) }
|
45
45
|
|
46
46
|
self.whitelisted_ransackable_associations = %w[taxonomy]
|
47
|
+
self.whitelisted_ransackable_attributes = %w[name permalink]
|
47
48
|
|
48
49
|
scope :for_stores, ->(stores) { joins(:taxonomy).where(spree_taxonomies: { store_id: stores.ids }) }
|
49
50
|
|
data/app/models/spree/variant.rb
CHANGED
@@ -60,7 +60,7 @@ module Spree
|
|
60
60
|
|
61
61
|
after_touch :clear_in_stock_cache
|
62
62
|
|
63
|
-
scope :in_stock, -> { joins(:stock_items).where(
|
63
|
+
scope :in_stock, -> { joins(:stock_items).where("#{Spree::StockItem.table_name}.count_on_hand > ? OR #{Spree::Variant.table_name}.track_inventory = ?", 0, false) }
|
64
64
|
scope :backorderable, -> { joins(:stock_items).where(spree_stock_items: { backorderable: true }) }
|
65
65
|
scope :in_stock_or_backorderable, -> { in_stock.or(backorderable) }
|
66
66
|
|
@@ -256,7 +256,13 @@ module Spree
|
|
256
256
|
end
|
257
257
|
end
|
258
258
|
|
259
|
-
|
259
|
+
def backorderable?
|
260
|
+
@backorderable ||= Rails.cache.fetch(['variant-backorderable', cache_key_with_version]) do
|
261
|
+
quantifier.backorderable?
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
delegate :total_on_hand, :can_supply?, to: :quantifier
|
260
266
|
|
261
267
|
alias is_backorderable? backorderable?
|
262
268
|
|
@@ -291,7 +297,7 @@ module Spree
|
|
291
297
|
end
|
292
298
|
|
293
299
|
def backordered?
|
294
|
-
@backordered ||=
|
300
|
+
@backordered ||= !in_stock? && stock_items.exists?(backorderable: true)
|
295
301
|
end
|
296
302
|
|
297
303
|
private
|
@@ -3,6 +3,26 @@ module Spree
|
|
3
3
|
class OptionsPresenter
|
4
4
|
FilterableOptionType = Struct.new(:option_type, :option_values, keyword_init: true) do
|
5
5
|
delegate_missing_to :option_type
|
6
|
+
|
7
|
+
def to_h
|
8
|
+
{
|
9
|
+
id: option_type.id,
|
10
|
+
name: option_type.name,
|
11
|
+
presentation: option_type.presentation,
|
12
|
+
option_values: option_values.map { |e| option_value_hash(e) }
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def option_value_hash(option_value)
|
19
|
+
{
|
20
|
+
id: option_value.id,
|
21
|
+
name: option_value.name,
|
22
|
+
presentation: option_value.presentation,
|
23
|
+
position: option_value.position
|
24
|
+
}
|
25
|
+
end
|
6
26
|
end
|
7
27
|
|
8
28
|
def initialize(option_values_scope:)
|
@@ -14,9 +14,29 @@ module Spree
|
|
14
14
|
property.uniq_values(product_properties_scope: product_properties)
|
15
15
|
end
|
16
16
|
|
17
|
+
def to_h
|
18
|
+
{
|
19
|
+
id: property.id,
|
20
|
+
name: property.name,
|
21
|
+
presentation: property.presentation,
|
22
|
+
values: values_hash
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
17
26
|
private
|
18
27
|
|
19
28
|
attr_reader :property
|
29
|
+
|
30
|
+
def values_hash
|
31
|
+
value_hashes = uniq_values.map do |filter_param, value|
|
32
|
+
{
|
33
|
+
value: value,
|
34
|
+
filter_param: filter_param
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
value_hashes.sort_by { |e| e[:value] }
|
39
|
+
end
|
20
40
|
end
|
21
41
|
end
|
22
42
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Spree
|
2
|
+
module Cart
|
3
|
+
class Associate
|
4
|
+
prepend Spree::ServiceModule::Base
|
5
|
+
|
6
|
+
def call(guest_order:, user:)
|
7
|
+
if guest_order.user.nil?
|
8
|
+
guest_order.associate_user!(user)
|
9
|
+
success(guest_order)
|
10
|
+
else
|
11
|
+
failure(guest_order, 'Already assigned to a user')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Spree
|
2
|
+
module Cart
|
3
|
+
class ChangeCurrency
|
4
|
+
prepend Spree::ServiceModule::Base
|
5
|
+
|
6
|
+
def call(order:, new_currency:)
|
7
|
+
return failure('Currency not supported') unless supported_currency?(order, new_currency)
|
8
|
+
|
9
|
+
result = order.update!(currency: new_currency) rescue false
|
10
|
+
|
11
|
+
if result
|
12
|
+
success(order)
|
13
|
+
else
|
14
|
+
failure('Failed to update order')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def supported_currency?(order, currency)
|
21
|
+
store = order.store
|
22
|
+
supported_currencies = store.supported_currencies_list
|
23
|
+
supported_currencies.map(&:iso_code).include?(currency.upcase)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -2,34 +2,46 @@ module Spree
|
|
2
2
|
class BaseSorter
|
3
3
|
def initialize(scope, params = {}, allowed_sort_attributes = [])
|
4
4
|
@scope = scope
|
5
|
-
@sort = params[:sort]
|
6
5
|
@allowed_sort_attributes = allowed_sort_attributes
|
6
|
+
@sort = sort_fields(params[:sort])
|
7
7
|
end
|
8
8
|
|
9
9
|
def call
|
10
|
-
|
10
|
+
by_param_attributes(scope)
|
11
11
|
end
|
12
12
|
|
13
13
|
protected
|
14
14
|
|
15
15
|
attr_reader :scope, :collection, :sort, :allowed_sort_attributes
|
16
16
|
|
17
|
-
def
|
18
|
-
return scope if
|
17
|
+
def by_param_attributes(scope)
|
18
|
+
return scope if sort.empty?
|
19
19
|
|
20
|
-
|
20
|
+
sort.each do |value, order|
|
21
|
+
next if value.blank? || allowed_sort_attributes.exclude?(value.to_sym)
|
22
|
+
|
23
|
+
scope = scope.order("#{value}": order)
|
24
|
+
end
|
25
|
+
|
26
|
+
scope
|
27
|
+
end
|
28
|
+
|
29
|
+
def sort_fields(sort)
|
30
|
+
return [] if sort.nil?
|
31
|
+
|
32
|
+
sort.split(',').map { |field| [sort_field(field), order_direction(field)] }
|
21
33
|
end
|
22
34
|
|
23
|
-
def desc_order
|
24
|
-
|
35
|
+
def desc_order(field)
|
36
|
+
String(field)[0] == '-'
|
25
37
|
end
|
26
38
|
|
27
|
-
def sort_field
|
28
|
-
|
39
|
+
def sort_field(field)
|
40
|
+
desc_order(field) ? field[1..-1] : field
|
29
41
|
end
|
30
42
|
|
31
|
-
def order_direction
|
32
|
-
desc_order ? :desc : :asc
|
43
|
+
def order_direction(field)
|
44
|
+
desc_order(field) ? :desc : :asc
|
33
45
|
end
|
34
46
|
end
|
35
47
|
end
|
@@ -7,8 +7,9 @@ module Spree
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def call
|
10
|
-
products =
|
10
|
+
products = by_param_attributes(scope)
|
11
11
|
products = by_price(products)
|
12
|
+
products = by_sku(products)
|
12
13
|
|
13
14
|
products.distinct
|
14
15
|
end
|
@@ -17,18 +18,33 @@ module Spree
|
|
17
18
|
|
18
19
|
attr_reader :sort, :scope, :currency, :allowed_sort_attributes
|
19
20
|
|
20
|
-
def price?
|
21
|
-
sort_field == 'price'
|
22
|
-
end
|
23
|
-
|
24
21
|
def by_price(scope)
|
25
|
-
return scope unless price
|
22
|
+
return scope unless (value = sort_by?('price'))
|
26
23
|
|
27
24
|
scope.joins(master: :prices).
|
28
25
|
select("#{Spree::Product.table_name}.*, #{Spree::Price.table_name}.amount").
|
29
26
|
distinct.
|
30
27
|
where(spree_prices: { currency: currency }).
|
31
|
-
order("#{Spree::Price.table_name}.amount #{
|
28
|
+
order("#{Spree::Price.table_name}.amount #{value[1]}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def by_sku(scope)
|
32
|
+
return scope unless (value = sort_by?('sku'))
|
33
|
+
|
34
|
+
select_product_attributes = if scope.to_sql.include?("#{Spree::Product.table_name}.*")
|
35
|
+
''
|
36
|
+
else
|
37
|
+
"#{Spree::Product.table_name}.*, "
|
38
|
+
end
|
39
|
+
|
40
|
+
scope.joins(:master).
|
41
|
+
select("#{select_product_attributes}#{Spree::Variant.table_name}.sku").
|
42
|
+
where(Spree::Variant.table_name.to_s => { is_master: true }).
|
43
|
+
order("#{Spree::Variant.table_name}.sku #{value[1]}")
|
44
|
+
end
|
45
|
+
|
46
|
+
def sort_by?(field)
|
47
|
+
sort.detect { |s| s[0] == field }
|
32
48
|
end
|
33
49
|
end
|
34
50
|
end
|
data/config/locales/en.yml
CHANGED
@@ -184,6 +184,12 @@ en:
|
|
184
184
|
spree/address:
|
185
185
|
one: Address
|
186
186
|
other: Addresses
|
187
|
+
spree/cms_page:
|
188
|
+
one: Page
|
189
|
+
other: Pages
|
190
|
+
spree/cms_section:
|
191
|
+
one: Section
|
192
|
+
other: Sections
|
187
193
|
spree/country:
|
188
194
|
one: Country
|
189
195
|
other: Countries
|
@@ -558,6 +564,7 @@ en:
|
|
558
564
|
draft_mode: Draft Mode
|
559
565
|
full_width: Full width
|
560
566
|
link_to_taxon: Link to Taxon
|
567
|
+
link_to_product: Link to Product
|
561
568
|
title: Title
|
562
569
|
fit: Fit To
|
563
570
|
info_hero_image_body: "<p>The Hero Image section adds a large image with a button and tagline text to your page.</p>
|
@@ -964,6 +971,8 @@ en:
|
|
964
971
|
error: error
|
965
972
|
errors:
|
966
973
|
messages:
|
974
|
+
store_association_can_not_be_changed: The store association can not be changed
|
975
|
+
store_is_already_set: Store is already set
|
967
976
|
blank: can't be blank
|
968
977
|
could_not_create_taxon: Could not create taxon
|
969
978
|
no_shipping_methods_available: No shipping methods available for selected location, please change your address and try again.
|
@@ -1132,7 +1141,7 @@ en:
|
|
1132
1141
|
log_in_to_continue: Log in to continue
|
1133
1142
|
logs: "Logs"
|
1134
1143
|
logged_in_as: Logged in as
|
1135
|
-
|
1144
|
+
logged_in_successfully: Logged in successfully
|
1136
1145
|
logged_out: You have been logged out.
|
1137
1146
|
login: Login
|
1138
1147
|
login_as_existing: Login as Existing Customer
|
@@ -1341,6 +1350,7 @@ en:
|
|
1341
1350
|
backordered_confirm_info: Selected item is backordered so expect delays. Are you sure you want to order it?
|
1342
1351
|
overview: Overview
|
1343
1352
|
package_from: package from
|
1353
|
+
page: Page
|
1344
1354
|
page_not_found: Sorry! Page you are looking can’t be found.
|
1345
1355
|
pagination:
|
1346
1356
|
next_page: next page »
|
@@ -1,10 +1,17 @@
|
|
1
1
|
class CreateSpreeProductsStores < ActiveRecord::Migration[5.2]
|
2
2
|
def up
|
3
|
-
|
3
|
+
if table_exists?(:spree_products_stores)
|
4
|
+
unless index_exists?(:spree_products_stores, [:product_id, :store_id], unique: true)
|
5
|
+
add_index :spree_products_stores, [:product_id, :store_id], unique: true
|
6
|
+
end
|
7
|
+
unless column_exists?(:spree_products_stores, :created_at)
|
8
|
+
add_timestamps :spree_products_stores, default: Time.current
|
9
|
+
end
|
10
|
+
else
|
4
11
|
create_table :spree_products_stores do |t|
|
5
12
|
t.references :product, index: true
|
6
13
|
t.references :store, index: true
|
7
|
-
t.timestamps
|
14
|
+
t.timestamps default: Time.current
|
8
15
|
|
9
16
|
t.index [:product_id, :store_id], unique: true
|
10
17
|
end
|
@@ -12,13 +19,13 @@ class CreateSpreeProductsStores < ActiveRecord::Migration[5.2]
|
|
12
19
|
stores = Spree::Store.all
|
13
20
|
product_ids = Spree::Product.with_deleted.order(:id).ids
|
14
21
|
|
15
|
-
|
16
|
-
|
17
|
-
|
22
|
+
if product_ids.any? && Spree::StoreProduct.respond_to?(:insert_all)
|
23
|
+
stores.find_each do |store|
|
24
|
+
records = product_ids.map { |product_id| { product_id: product_id, store_id: store.id } }
|
18
25
|
|
19
|
-
|
20
|
-
|
21
|
-
|
26
|
+
# Rails 5 does not have insert_all
|
27
|
+
Spree::StoreProduct.insert_all(records)
|
28
|
+
end
|
22
29
|
end
|
23
30
|
end
|
24
31
|
end
|
@@ -22,6 +22,20 @@ module Spree
|
|
22
22
|
current_store.default_locale
|
23
23
|
end
|
24
24
|
|
25
|
+
def ensure_current_store(object)
|
26
|
+
return if object.nil?
|
27
|
+
|
28
|
+
if object.has_attribute?(:store_id)
|
29
|
+
if object.store.present? && object.store != current_store
|
30
|
+
raise Spree.t('errors.messages.store_is_already_set')
|
31
|
+
else
|
32
|
+
object.store = current_store
|
33
|
+
end
|
34
|
+
elsif object.class.method_defined?(:stores) && object.stores.exclude?(current_store)
|
35
|
+
object.stores << current_store
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
25
39
|
# Return a Hash of things that influence the prices displayed in your shop.
|
26
40
|
#
|
27
41
|
# By default, the only thing that influences prices that is the current order's +tax_zone+
|
data/lib/spree/core/version.rb
CHANGED
@@ -8,6 +8,8 @@ module Spree
|
|
8
8
|
:image_attributes,
|
9
9
|
:inventory_unit_attributes,
|
10
10
|
:line_item_attributes,
|
11
|
+
:menu_attributes,
|
12
|
+
:menu_item_attributes,
|
11
13
|
:option_type_attributes,
|
12
14
|
:option_value_attributes,
|
13
15
|
:payment_attributes,
|
@@ -62,6 +64,11 @@ module Spree
|
|
62
64
|
|
63
65
|
@@line_item_attributes = [:id, :variant_id, :quantity]
|
64
66
|
|
67
|
+
@@menu_attributes = [:name, :locale, :location]
|
68
|
+
|
69
|
+
@@menu_item_attributes = [:name, :subtite, :destination, :new_window, :item_type,
|
70
|
+
:linked_resource_type, :linked_resource_id, :code, :menu_id]
|
71
|
+
|
65
72
|
@@option_type_attributes = [:name, :presentation, :option_values_attributes]
|
66
73
|
|
67
74
|
@@option_value_attributes = [:name, :presentation]
|
@@ -36,6 +36,12 @@ FactoryBot.define do
|
|
36
36
|
after :create do |product|
|
37
37
|
product.master.stock_items.first.adjust_count_on_hand(10)
|
38
38
|
end
|
39
|
+
|
40
|
+
trait :without_backorder do
|
41
|
+
after :create do |product|
|
42
|
+
product.master.stock_items.update_all(backorderable: false)
|
43
|
+
end
|
44
|
+
end
|
39
45
|
end
|
40
46
|
|
41
47
|
factory :product_with_option_types do
|
@@ -48,7 +48,7 @@ module Spree
|
|
48
48
|
remember_me: 'Se souvenir de moi',
|
49
49
|
my_account: 'Mon compte',
|
50
50
|
my_orders: 'Mes commandes',
|
51
|
-
|
51
|
+
logged_in_successfully: 'Connexion réussie'
|
52
52
|
})
|
53
53
|
end
|
54
54
|
# rubocop:enable Layout/ArgumentAlignment
|
@@ -7,4 +7,9 @@ RSpec.configure do |config|
|
|
7
7
|
config.around :each, type: :feature do |ex|
|
8
8
|
ex.run_with_retry retry: ENV.fetch('RSPEC_RETRY_RETRY_COUNT', 3).to_i
|
9
9
|
end
|
10
|
+
|
11
|
+
# callback to be run between retries
|
12
|
+
config.retry_callback = proc do |ex|
|
13
|
+
Rails.cache.clear
|
14
|
+
end
|
10
15
|
end
|
data/spree_core.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.metadata = {
|
17
17
|
"bug_tracker_uri" => "https://github.com/spree/spree/issues",
|
18
18
|
"changelog_uri" => "https://github.com/spree/spree/releases/tag/v#{s.version}",
|
19
|
-
"documentation_uri" => "https://
|
19
|
+
"documentation_uri" => "https://dev-docs.spreecommerce.org/",
|
20
20
|
"source_code_uri" => "https://github.com/spree/spree/tree/v#{s.version}",
|
21
21
|
}
|
22
22
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spree_core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.3.
|
4
|
+
version: 4.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Schofield
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2022-01-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionpack
|
@@ -472,6 +472,7 @@ files:
|
|
472
472
|
- app/models/concerns/spree/display_link.rb
|
473
473
|
- app/models/concerns/spree/display_money.rb
|
474
474
|
- app/models/concerns/spree/filter_param.rb
|
475
|
+
- app/models/concerns/spree/image_methods.rb
|
475
476
|
- app/models/concerns/spree/memoized_data.rb
|
476
477
|
- app/models/concerns/spree/multi_store_resource.rb
|
477
478
|
- app/models/concerns/spree/named_type.rb
|
@@ -483,6 +484,7 @@ files:
|
|
483
484
|
- app/models/concerns/spree/user_methods.rb
|
484
485
|
- app/models/concerns/spree/user_payment_source.rb
|
485
486
|
- app/models/concerns/spree/user_reporting.rb
|
487
|
+
- app/models/concerns/spree/user_roles.rb
|
486
488
|
- app/models/concerns/spree/vat_price_calculation.rb
|
487
489
|
- app/models/friendly_id/slug_decorator.rb
|
488
490
|
- app/models/spree/ability.rb
|
@@ -697,6 +699,8 @@ files:
|
|
697
699
|
- app/services/spree/account/update.rb
|
698
700
|
- app/services/spree/build_localized_redirect_url.rb
|
699
701
|
- app/services/spree/cart/add_item.rb
|
702
|
+
- app/services/spree/cart/associate.rb
|
703
|
+
- app/services/spree/cart/change_currency.rb
|
700
704
|
- app/services/spree/cart/create.rb
|
701
705
|
- app/services/spree/cart/destroy.rb
|
702
706
|
- app/services/spree/cart/empty.rb
|
@@ -722,7 +726,6 @@ files:
|
|
722
726
|
- app/sorters/spree/products/sort.rb
|
723
727
|
- app/validators/db_maximum_length_validator.rb
|
724
728
|
- app/validators/email_validator.rb
|
725
|
-
- app/views/spree/shared/_purchased_items_table.text.erb
|
726
729
|
- config/initializers/active_storage.rb
|
727
730
|
- config/initializers/friendly_id.rb
|
728
731
|
- config/initializers/inflections.rb
|
@@ -1192,9 +1195,9 @@ licenses:
|
|
1192
1195
|
- BSD-3-Clause
|
1193
1196
|
metadata:
|
1194
1197
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
1195
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v4.3.
|
1196
|
-
documentation_uri: https://
|
1197
|
-
source_code_uri: https://github.com/spree/spree/tree/v4.3.
|
1198
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v4.3.1
|
1199
|
+
documentation_uri: https://dev-docs.spreecommerce.org/
|
1200
|
+
source_code_uri: https://github.com/spree/spree/tree/v4.3.1
|
1198
1201
|
post_install_message:
|
1199
1202
|
rdoc_options: []
|
1200
1203
|
require_paths:
|
@@ -1210,7 +1213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1210
1213
|
- !ruby/object:Gem::Version
|
1211
1214
|
version: 1.8.23
|
1212
1215
|
requirements: []
|
1213
|
-
rubygems_version: 3.2.
|
1216
|
+
rubygems_version: 3.2.22
|
1214
1217
|
signing_key:
|
1215
1218
|
specification_version: 4
|
1216
1219
|
summary: The bare bones necessary for Spree
|
@@ -1,25 +0,0 @@
|
|
1
|
-
<% line_items.each do |item| %>
|
2
|
-
<%= item.variant.sku %> <%= raw(item.variant.product.name) %> <%= raw(item.variant.options_text) -%> (<%=item.quantity%>) <%= Spree.t('at_symbol') %> <%= item.single_money %> = <%= item.display_amount %>
|
3
|
-
<% end %>
|
4
|
-
============================================================
|
5
|
-
<%= Spree.t('order_mailer.subtotal') %> <%= order.display_item_total %>
|
6
|
-
<% if order.line_item_adjustments.exists? %>
|
7
|
-
<% if order.all_adjustments.promotion.eligible.exists? %>
|
8
|
-
<% order.all_adjustments.promotion.eligible.group_by(&:label).each do |label, adjustments| %>
|
9
|
-
<%= Spree.t(:promotion) %>: <%= label %> <%= Spree::Money.new(adjustments.sum(&:amount), currency: order.currency) %>
|
10
|
-
<% end %>
|
11
|
-
<% end %>
|
12
|
-
<% end %>
|
13
|
-
|
14
|
-
<% order.shipments.group_by { |s| s.selected_shipping_rate.try(:name) }.each do |name, shipments| %>
|
15
|
-
<%= Spree.t(:shipping) %>: <%= name %> <%= Spree::Money.new(shipments.sum(&:discounted_cost), currency: order.currency) %>
|
16
|
-
<% end %>
|
17
|
-
|
18
|
-
<% if order.additional_tax_total != 0 %>
|
19
|
-
<%= Spree.t(:tax) %>: <%= order.display_additional_tax_total.to_html %>
|
20
|
-
<% end %>
|
21
|
-
|
22
|
-
<% order.adjustments.eligible.each do |adjustment| %>
|
23
|
-
<% next if (adjustment.source_type == 'Spree::TaxRate') and (adjustment.amount == 0) %>
|
24
|
-
<%= adjustment.label %> <%= adjustment.display_amount %>
|
25
|
-
<% end %>
|