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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/spree.js +0 -1
- data/app/finders/spree/products/find.rb +19 -6
- data/app/finders/spree/variants/option_types_finder.rb +21 -0
- data/app/finders/spree/variants/visible_finder.rb +22 -0
- data/app/helpers/spree/base_helper.rb +48 -18
- data/app/helpers/spree/products_helper.rb +76 -8
- data/app/models/concerns/spree/user_methods.rb +2 -2
- data/app/models/spree/app_dependencies.rb +1 -7
- data/app/models/spree/credit_card.rb +4 -5
- data/app/models/spree/image.rb +52 -3
- data/app/models/spree/image/configuration/active_storage.rb +9 -1
- data/app/models/spree/line_item.rb +1 -2
- data/app/models/spree/option_type.rb +4 -0
- data/app/models/spree/order.rb +12 -12
- data/app/models/spree/order/address_book.rb +20 -7
- data/app/models/spree/payment_method.rb +8 -0
- data/app/models/spree/preferences/preferable.rb +1 -1
- data/app/models/spree/product.rb +7 -6
- data/app/models/spree/promotion/actions/create_item_adjustments.rb +1 -1
- data/app/models/spree/promotion_handler/coupon.rb +2 -1
- data/app/models/spree/return_item/eligibility_validator/base_validator.rb +1 -1
- data/app/models/spree/store.rb +2 -1
- data/app/models/spree/taxon.rb +2 -6
- data/app/models/spree/variant.rb +2 -14
- data/app/models/spree/zone.rb +6 -3
- data/app/presenters/spree/product_summary_presenter.rb +26 -0
- data/app/presenters/spree/variant_presenter.rb +69 -0
- data/app/presenters/spree/variants/option_types_presenter.rb +74 -0
- data/app/presenters/spree/variants/options_presenter.rb +49 -0
- data/app/services/spree/checkout/get_shipping_rates.rb +10 -7
- data/app/services/spree/checkout/update.rb +2 -13
- data/config/locales/en.yml +156 -14
- data/db/default/spree/stores.rb +8 -3
- data/db/migrate/20140309033438_create_store_from_preferences.rb +8 -4
- data/db/migrate/20191005121504_add_store_id_to_payment_methods.rb +7 -0
- data/db/migrate/20191016134113_add_deafult_value_for_store_default_currency.rb +5 -0
- data/db/migrate/20200102141311_add_social_to_spree_stores.rb +7 -0
- data/lib/generators/spree/dummy/dummy_generator.rb +2 -1
- data/lib/generators/spree/dummy/templates/initializers/bullet.rb +5 -0
- data/lib/generators/spree/install/install_generator.rb +13 -5
- data/lib/generators/spree/install/templates/config/initializers/spree.rb +0 -1
- data/lib/generators/spree/install/templates/config/initializers/spree_storefront.rb +1 -0
- data/lib/generators/spree/install/templates/config/spree_storefront.yml +67 -0
- data/lib/spree/core.rb +0 -1
- data/lib/spree/core/controller_helpers/order.rb +12 -6
- data/lib/spree/core/controller_helpers/store.rb +2 -2
- data/lib/spree/core/search/base.rb +59 -22
- data/lib/spree/core/version.rb +1 -3
- data/lib/spree/money.rb +8 -1
- data/lib/spree/permitted_attributes.rb +3 -2
- data/lib/spree/testing_support/capybara_ext.rb +0 -45
- data/lib/spree/testing_support/common_rake.rb +1 -1
- data/lib/spree/testing_support/factories/store_factory.rb +3 -0
- data/lib/spree/testing_support/order_walkthrough.rb +7 -3
- data/spree_core.gemspec +8 -14
- metadata +45 -24
- data/app/finders/spree/addresses/find.rb +0 -17
- data/app/services/spree/account/addresses/base.rb +0 -39
- data/app/services/spree/account/addresses/create.rb +0 -18
- data/app/services/spree/account/addresses/update.rb +0 -18
- data/lib/spree/database_type_utilities.rb +0 -12
@@ -15,7 +15,15 @@ module Spree
|
|
15
15
|
mini: '48x48>',
|
16
16
|
small: '100x100>',
|
17
17
|
product: '240x240>',
|
18
|
-
|
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
|
|
@@ -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
|
data/app/models/spree/order.rb
CHANGED
@@ -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(
|
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)
|
@@ -55,18 +55,31 @@ module Spree
|
|
55
55
|
def update_or_create_address(attributes = {})
|
56
56
|
return if attributes.blank?
|
57
57
|
|
58
|
-
attributes.
|
58
|
+
attributes = attributes.select { |_k, v| v.present? }
|
59
59
|
|
60
|
-
|
61
|
-
|
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
|
-
|
64
|
-
|
69
|
+
if address&.editable?
|
70
|
+
address.update(attributes)
|
71
|
+
return address
|
72
|
+
else
|
73
|
+
attributes.delete(:id)
|
74
|
+
end
|
75
|
+
end
|
65
76
|
|
66
|
-
|
77
|
+
unless attributes[:id]
|
78
|
+
address = Spree::Address.new(attributes)
|
79
|
+
address.save
|
67
80
|
end
|
68
81
|
|
69
|
-
|
82
|
+
address
|
70
83
|
end
|
71
84
|
end
|
72
85
|
end
|
@@ -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
|
data/app/models/spree/product.rb
CHANGED
@@ -110,7 +110,7 @@ module Spree
|
|
110
110
|
|
111
111
|
alias options product_option_types
|
112
112
|
|
113
|
-
self.whitelisted_ransackable_associations = %w[
|
113
|
+
self.whitelisted_ransackable_associations = %w[stores variants_including_master master variants]
|
114
114
|
self.whitelisted_ransackable_attributes = %w[description name slug discontinue_on]
|
115
115
|
self.whitelisted_ransackable_scopes = %w[not_discontinued]
|
116
116
|
|
@@ -239,9 +239,7 @@ module Spree
|
|
239
239
|
# values should not be displayed to frontend users. Otherwise it breaks the
|
240
240
|
# idea of having variants
|
241
241
|
def variants_and_option_values(current_currency = nil)
|
242
|
-
variants.
|
243
|
-
variant.option_values.any?
|
244
|
-
end
|
242
|
+
variants.active(current_currency).joins(:option_value_variants)
|
245
243
|
end
|
246
244
|
|
247
245
|
def empty_option_values?
|
@@ -284,7 +282,10 @@ module Spree
|
|
284
282
|
end
|
285
283
|
|
286
284
|
def category
|
287
|
-
taxons.joins(:taxonomy).
|
285
|
+
taxons.joins(:taxonomy).
|
286
|
+
where(spree_taxonomies: { name: Spree.t(:taxonomy_categories_name) }).
|
287
|
+
order(depth: :desc).
|
288
|
+
first
|
288
289
|
end
|
289
290
|
|
290
291
|
private
|
@@ -321,7 +322,7 @@ module Spree
|
|
321
322
|
price: master.price
|
322
323
|
)
|
323
324
|
end
|
324
|
-
save
|
325
|
+
throw(:abort) unless save
|
325
326
|
end
|
326
327
|
|
327
328
|
def ensure_master
|
@@ -23,7 +23,7 @@ module Spree
|
|
23
23
|
order = line_item.order
|
24
24
|
|
25
25
|
# Prevent negative order totals
|
26
|
-
amounts << order.amount - order.adjustments.
|
26
|
+
amounts << order.amount - order.adjustments.sum(:amount).abs if order.adjustments.any?
|
27
27
|
|
28
28
|
amounts.min * -1
|
29
29
|
end
|
@@ -25,6 +25,7 @@ module Spree
|
|
25
25
|
|
26
26
|
def remove(coupon_code)
|
27
27
|
promotion = order.promotions.with_coupon_code(coupon_code)
|
28
|
+
|
28
29
|
if promotion.present?
|
29
30
|
# Order promotion has to be destroyed before line item removing
|
30
31
|
order.order_promotions.find_by!(promotion_id: promotion.id).destroy
|
@@ -75,7 +76,7 @@ module Spree
|
|
75
76
|
line_item = order.find_line_item_by_variant(item.variant)
|
76
77
|
next if line_item.blank?
|
77
78
|
|
78
|
-
Spree::Dependencies.cart_remove_item_service
|
79
|
+
Spree::Dependencies.cart_remove_item_service(order: order, item: item.variant, quantity: item.quantity)
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
data/app/models/spree/store.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module Spree
|
2
2
|
class Store < Spree::Base
|
3
3
|
has_many :orders, class_name: 'Spree::Order'
|
4
|
+
has_many :payment_methods, class_name: 'Spree::PaymentMethod'
|
4
5
|
|
5
6
|
with_options presence: true do
|
6
|
-
validates :code, uniqueness: { case_sensitive: false, allow_blank: true }
|
7
7
|
validates :name, :url, :mail_from_address
|
8
|
+
validates :default_currency
|
8
9
|
end
|
9
10
|
|
10
11
|
before_save :ensure_default_exists_and_is_unique
|
data/app/models/spree/taxon.rb
CHANGED
@@ -48,13 +48,9 @@ module Spree
|
|
48
48
|
fs
|
49
49
|
end
|
50
50
|
|
51
|
-
# Return meta_title if set otherwise generates from
|
51
|
+
# Return meta_title if set otherwise generates from taxon name
|
52
52
|
def seo_title
|
53
|
-
|
54
|
-
root? ? name : "#{root.name} - #{name}"
|
55
|
-
else
|
56
|
-
meta_title
|
57
|
-
end
|
53
|
+
meta_title.blank? ? name : meta_title
|
58
54
|
end
|
59
55
|
|
60
56
|
# Creates permalink base for friendly_id
|
data/app/models/spree/variant.rb
CHANGED
@@ -116,15 +116,7 @@ module Spree
|
|
116
116
|
end
|
117
117
|
|
118
118
|
def options_text
|
119
|
-
|
120
|
-
a.option_type.position <=> b.option_type.position
|
121
|
-
end
|
122
|
-
|
123
|
-
values.to_a.map! do |ov|
|
124
|
-
"#{ov.option_type.presentation}: #{ov.presentation}"
|
125
|
-
end
|
126
|
-
|
127
|
-
values.to_sentence(words_connector: ', ', two_words_connector: ', ')
|
119
|
+
Spree::Variants::OptionsPresenter.new(self).to_sentence
|
128
120
|
end
|
129
121
|
|
130
122
|
# Default to master name
|
@@ -234,11 +226,7 @@ module Spree
|
|
234
226
|
end
|
235
227
|
|
236
228
|
def in_stock?
|
237
|
-
|
238
|
-
# Check if model responds to cache version and fall back to updated_at for older rails versions
|
239
|
-
# This makes sure a version is supplied when recyclable cache keys are disabled.
|
240
|
-
version = respond_to?(:cache_version) ? cache_version : updated_at.to_i
|
241
|
-
Rails.cache.fetch(in_stock_cache_key, version: version) do
|
229
|
+
Rails.cache.fetch(in_stock_cache_key) do
|
242
230
|
total_on_hand > 0
|
243
231
|
end
|
244
232
|
end
|
data/app/models/spree/zone.rb
CHANGED
@@ -25,7 +25,9 @@ module Spree
|
|
25
25
|
self.whitelisted_ransackable_attributes = ['description']
|
26
26
|
|
27
27
|
def self.default_tax
|
28
|
-
|
28
|
+
Rails.cache.fetch('default_tax') do
|
29
|
+
find_by(default_tax: true)
|
30
|
+
end
|
29
31
|
end
|
30
32
|
|
31
33
|
def self.potential_matching_zones(zone)
|
@@ -69,8 +71,8 @@ module Spree
|
|
69
71
|
end
|
70
72
|
|
71
73
|
def kind
|
72
|
-
if
|
73
|
-
|
74
|
+
if kind?
|
75
|
+
super
|
74
76
|
else
|
75
77
|
not_nil_scope = members.where.not(zoneable_type: nil)
|
76
78
|
zone_type = not_nil_scope.order('created_at ASC').pluck(:zoneable_type).last
|
@@ -173,6 +175,7 @@ module Spree
|
|
173
175
|
|
174
176
|
def remove_previous_default
|
175
177
|
Spree::Zone.with_default_tax.where.not(id: id).update_all(default_tax: false)
|
178
|
+
Rails.cache.delete('default_zone')
|
176
179
|
end
|
177
180
|
|
178
181
|
def set_zone_members(ids, type)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Spree
|
2
|
+
class ProductSummaryPresenter
|
3
|
+
include Rails.application.routes.url_helpers
|
4
|
+
|
5
|
+
def initialize(product)
|
6
|
+
@product = product
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
{
|
11
|
+
name: @product.name,
|
12
|
+
images: images
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def images
|
19
|
+
@product.images.map do |image|
|
20
|
+
{
|
21
|
+
url_product: rails_representation_url(image.url(:product), only_path: true)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Spree
|
2
|
+
class VariantPresenter
|
3
|
+
include Rails.application.routes.url_helpers
|
4
|
+
include Spree::BaseHelper
|
5
|
+
|
6
|
+
attr_reader :current_currency, :current_price_options
|
7
|
+
|
8
|
+
def initialize(opts = {})
|
9
|
+
@variants = opts[:variants]
|
10
|
+
@is_product_available_in_currency = opts[:is_product_available_in_currency]
|
11
|
+
@current_currency = opts[:current_currency]
|
12
|
+
@current_price_options = opts[:current_price_options]
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
@variants.map do |variant|
|
17
|
+
{
|
18
|
+
display_price: display_price(variant),
|
19
|
+
is_product_available_in_currency: @is_product_available_in_currency,
|
20
|
+
backorderable: backorderable?(variant),
|
21
|
+
images: images(variant),
|
22
|
+
option_values: option_values(variant),
|
23
|
+
}.merge(
|
24
|
+
variant_attributes(variant)
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def images(variant)
|
30
|
+
variant.images.map do |image|
|
31
|
+
{
|
32
|
+
alt: image.alt,
|
33
|
+
url_product: rails_representation_url(image.url(:product), only_path: true)
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def option_values(variant)
|
39
|
+
variant.option_values.map do |option_value|
|
40
|
+
{
|
41
|
+
id: option_value.id,
|
42
|
+
name: option_value.name,
|
43
|
+
presentation: option_value.presentation,
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def backorderable?(variant)
|
51
|
+
backorderable_variant_ids.include?(variant.id)
|
52
|
+
end
|
53
|
+
|
54
|
+
def backorderable_variant_ids
|
55
|
+
@backorderable_variant_ids ||= Spree::Variant.joins(:stock_items).where(id: @variants.map(&:id)).
|
56
|
+
where(spree_stock_items: { backorderable: true }).merge(Spree::StockItem.with_active_stock_location).distinct.ids
|
57
|
+
end
|
58
|
+
|
59
|
+
def variant_attributes(variant)
|
60
|
+
{
|
61
|
+
id: variant.id,
|
62
|
+
sku: variant.sku,
|
63
|
+
price: variant.price,
|
64
|
+
in_stock: variant.in_stock?,
|
65
|
+
purchasable: variant.purchasable?
|
66
|
+
}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Spree
|
2
|
+
module Variants
|
3
|
+
class OptionTypesPresenter
|
4
|
+
def initialize(option_types)
|
5
|
+
@option_types = option_types
|
6
|
+
end
|
7
|
+
|
8
|
+
def default_variant
|
9
|
+
default_variant_data[:variant]
|
10
|
+
end
|
11
|
+
|
12
|
+
def options
|
13
|
+
option_types.map do |option_type|
|
14
|
+
{
|
15
|
+
id: option_type.id,
|
16
|
+
name: option_type.name,
|
17
|
+
presentation: option_type.presentation,
|
18
|
+
position: option_type.position,
|
19
|
+
option_values: option_values_options(option_type.option_values)
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :option_types
|
27
|
+
|
28
|
+
def default_variant_data
|
29
|
+
return {} if option_types.empty?
|
30
|
+
|
31
|
+
@default_variant_data ||= begin
|
32
|
+
find_in_stock_variant_data || find_backorderable_variant_data || find_first_variant_data
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def find_in_stock_variant_data
|
37
|
+
find_variant_data(&:in_stock?)
|
38
|
+
end
|
39
|
+
|
40
|
+
def find_backorderable_variant_data
|
41
|
+
find_variant_data(&:backorderable?)
|
42
|
+
end
|
43
|
+
|
44
|
+
def find_variant_data(&block)
|
45
|
+
option_types.first.option_values.each do |option_value|
|
46
|
+
variant = option_value.variants.find(&block)
|
47
|
+
|
48
|
+
return { variant: variant, option_value: option_value } if variant
|
49
|
+
end
|
50
|
+
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def find_first_variant_data
|
55
|
+
option_value = option_types.first.option_values.first
|
56
|
+
variant = option_value.variants.first
|
57
|
+
|
58
|
+
{ variant: variant, option_value: option_value }
|
59
|
+
end
|
60
|
+
|
61
|
+
def option_values_options(option_values)
|
62
|
+
option_values.map do |option_value|
|
63
|
+
{
|
64
|
+
id: option_value.id,
|
65
|
+
position: option_value.position,
|
66
|
+
presentation: option_value.presentation,
|
67
|
+
variant_id: option_value.variants.first.id,
|
68
|
+
is_default: option_value == default_variant_data[:option_value]
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|