spree_core 4.1.0.rc3 → 4.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7062a9bb28afea833ef56e653f7f974eaf33f6d10c352c407beea07910ed2b7e
4
- data.tar.gz: 0effc4f253609ec14cd29109e21161b44cb92af1c1a53840f24bd27dae5fd0d8
3
+ metadata.gz: 3057b4eecebae24385eed939c3236d14177222693d927f85e7fac5ac775cbdec
4
+ data.tar.gz: 8f5f40c80e021a02bb985b119f9c6f5e90d268392b81984df85d0f738208866e
5
5
  SHA512:
6
- metadata.gz: 5024b7281e7cfa97efbb104d6f243d9783d36288d5dfe8e91a8ebe14a52e04bc61f78e7cf8a3765224d8a9a7ea4e18d218b0e9d924c12b111a629544ed36ddf9
7
- data.tar.gz: dc6c98bf3679d2997e966f1efc671d87523fb994650fdff5968ed2c52523171a60c9b406f93c645bb34a52a1c5fbfc9215d1f574bc52a955082f54fba255cb3c
6
+ metadata.gz: a495af06eebc663bb6c69ccf12b411989f8283ac36edd633b21421bf0b152dbc91315515ea1c5189a1c4b43f45d397fd1d076ad9e35c08e35bdf8f6df573d50e
7
+ data.tar.gz: e559d035f7ef2359141281dbc4d42dd2f0791ac0c42f7ecc47a638ba0f1dd1bffab385e35389b70409ce1bf856c609a4dabf7edbbb428778f05545e12269b726
@@ -25,6 +25,8 @@ module Spree
25
25
  def link_to_tracking(shipment, options = {})
26
26
  return unless shipment.tracking && shipment.shipping_method
27
27
 
28
+ options[:target] ||= :blank
29
+
28
30
  if shipment.tracking_url
29
31
  link_to(shipment.tracking, shipment.tracking_url, options)
30
32
  else
@@ -104,15 +106,27 @@ module Spree
104
106
  Spree::Core::Engine.frontend_available?
105
107
  end
106
108
 
109
+ # we should always try to render image of the default variant
110
+ # same as it's done on PDP
111
+ def default_image_for_product(product)
112
+ if product.default_variant.images.any?
113
+ product.default_variant.images.first
114
+ elsif product.variant_images.any?
115
+ product.variant_images.first
116
+ end
117
+ end
118
+
107
119
  def default_image_for_product_or_variant(product_or_variant)
108
- if product_or_variant.images.empty?
109
- if product_or_variant.is_a?(Spree::Product) && product_or_variant.variant_images.any?
110
- product_or_variant.variant_images.first
111
- elsif product_or_variant.is_a?(Spree::Variant) && product_or_variant.product.variant_images.any?
112
- product_or_variant.product.variant_images.first
120
+ Rails.cache.fetch("spree/default-image/#{product_or_variant.cache_key_with_version}") do
121
+ if product_or_variant.is_a?(Spree::Product)
122
+ default_image_for_product(product_or_variant)
123
+ elsif product_or_variant.is_a?(Spree::Variant)
124
+ if product_or_variant.images.any?
125
+ product_or_variant.images.first
126
+ else
127
+ default_image_for_product(product_or_variant.product)
128
+ end
113
129
  end
114
- else
115
- product_or_variant.images.first
116
130
  end
117
131
  end
118
132
 
@@ -31,12 +31,12 @@ module Spree
31
31
  end
32
32
  end
33
33
 
34
- def default_variant(variants)
35
- variants_option_types_presenter(variants).default_variant || variants.find(&:is_master)
34
+ def default_variant(variants, product)
35
+ variants_option_types_presenter(variants, product).default_variant || product.default_variant
36
36
  end
37
37
 
38
- def used_variants_options(variants)
39
- variants_option_types_presenter(variants).options
38
+ def used_variants_options(variants, product)
39
+ variants_option_types_presenter(variants, product).options
40
40
  end
41
41
 
42
42
  # converts line breaks in product description into <p> tags (for html display purposes)
@@ -94,10 +94,12 @@ module Spree
94
94
  end
95
95
 
96
96
  def product_images(product, variants)
97
- variants = if product.variants_and_option_values(current_currency).any?
98
- variants.reject(&:is_master)
99
- else
100
- variants
97
+ if product.variants_and_option_values(current_currency).any?
98
+ variants_without_master_images = variants.reject(&:is_master).map(&:images).flatten
99
+
100
+ if variants_without_master_images.any?
101
+ return variants_without_master_images
102
+ end
101
103
  end
102
104
 
103
105
  variants.map(&:images).flatten
@@ -143,11 +145,11 @@ module Spree
143
145
  end
144
146
  end
145
147
 
146
- def variants_option_types_presenter(variants)
148
+ def variants_option_types_presenter(variants, product)
147
149
  @_variants_option_types_presenter ||= begin
148
150
  option_types = Spree::Variants::OptionTypesFinder.new(variant_ids: variants.map(&:id)).execute
149
151
 
150
- Spree::Variants::OptionTypesPresenter.new(option_types, variants)
152
+ Spree::Variants::OptionTypesPresenter.new(option_types, variants, product)
151
153
  end
152
154
  end
153
155
  end
@@ -21,7 +21,8 @@ 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
24
+ :shipment_total, :promo_total, :total,
25
+ :cart_promo_total
25
26
 
26
27
  alias display_ship_total display_shipment_total
27
28
  alias_attribute :ship_total, :shipment_total
@@ -631,6 +632,15 @@ module Spree
631
632
  coupons
632
633
  end
633
634
 
635
+ # Returns item and whole order discount amount for Order
636
+ # without Shipment disccounts (eg. Free Shipping)
637
+ # @return [BigDecimal]
638
+ def cart_promo_total
639
+ all_adjustments.eligible.nonzero.promotion.
640
+ where.not(adjustable_type: 'Spree::Shipment').
641
+ sum(:amount)
642
+ end
643
+
634
644
  private
635
645
 
636
646
  def link_by_email
@@ -15,6 +15,8 @@ module Spree
15
15
  end
16
16
 
17
17
  def could_use_store_credit?
18
+ return false if Spree::PaymentMethod::StoreCredit.available.empty?
19
+
18
20
  total_available_store_credit > 0
19
21
  end
20
22
 
@@ -75,6 +75,7 @@ module Spree
75
75
  has_many :orders, through: :line_items
76
76
 
77
77
  has_many :variant_images, -> { order(:position) }, source: :images, through: :variants_including_master
78
+ has_many :variant_images_without_master, -> { order(:position) }, source: :images, through: :variants
78
79
 
79
80
  after_create :add_associations_from_prototype
80
81
  after_create :build_variants_from_option_values_hash, if: :option_values_hash
@@ -150,10 +151,28 @@ module Spree
150
151
  variants.any?
151
152
  end
152
153
 
154
+ # Returns default Variant for Product
155
+ # If `track_inventory_levels` is enabled it will try to find the first Variant
156
+ # in stock or backorderable, if there's none it will return first Variant sorted
157
+ # by `position` attribute
158
+ # If `track_inventory_levels` is disabled it will return first Variant sorted
159
+ # by `position` attribute
160
+ #
161
+ # @return [Spree::Variant]
153
162
  def default_variant
154
- has_variants? ? variants.first : master
163
+ track_inventory = Spree::Config[:track_inventory_levels]
164
+
165
+ Rails.cache.fetch("spree/default-variant/#{cache_key_with_version}/#{track_inventory}") do
166
+ if track_inventory && variants.in_stock_or_backorderable.any?
167
+ variants.in_stock_or_backorderable.first
168
+ else
169
+ has_variants? ? variants.first : master
170
+ end
171
+ end
155
172
  end
156
173
 
174
+ # Returns default Variant ID for Product
175
+ # @return [Integer]
157
176
  def default_variant_id
158
177
  default_variant.id
159
178
  end
@@ -40,6 +40,7 @@ module Spree
40
40
  scope :with_state, ->(*s) { where(state: s) }
41
41
  # sort by most recent shipped_at, falling back to created_at. add "id desc" to make specs that involve this scope more deterministic.
42
42
  scope :reverse_chronological, -> { order(Arel.sql('coalesce(spree_shipments.shipped_at, spree_shipments.created_at) desc'), id: :desc) }
43
+ scope :valid, -> { where.not(state: :canceled) }
43
44
 
44
45
  # shipment state machine (see http://github.com/pluginaweek/state_machine/tree/master for details)
45
46
  state_machine initial: :pending, use_transactions: false do
@@ -18,6 +18,7 @@ module Spree
18
18
  display_price: display_price(variant),
19
19
  is_product_available_in_currency: @is_product_available_in_currency,
20
20
  backorderable: backorderable?(variant),
21
+ in_stock: in_stock?(variant),
21
22
  images: images(variant),
22
23
  option_values: option_values(variant),
23
24
  }.merge(
@@ -52,16 +53,21 @@ module Spree
52
53
  end
53
54
 
54
55
  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
56
+ @backorderable_variant_ids ||= Spree::Variant.where(id: @variants.map(&:id)).backorderable.ids
57
+ end
58
+
59
+ def in_stock?(variant)
60
+ in_stock_variant_ids.include?(variant.id)
61
+ end
62
+
63
+ def in_stock_variant_ids
64
+ @in_stock_variant_ids ||= Spree::Variant.where(id: @variants.map(&:id)).in_stock.ids
57
65
  end
58
66
 
59
67
  def variant_attributes(variant)
60
68
  {
61
69
  id: variant.id,
62
70
  sku: variant.sku,
63
- price: variant.price,
64
- in_stock: variant.in_stock?,
65
71
  purchasable: variant.purchasable?
66
72
  }
67
73
  end
@@ -1,9 +1,10 @@
1
1
  module Spree
2
2
  module Variants
3
3
  class OptionTypesPresenter
4
- def initialize(option_types, variants)
4
+ def initialize(option_types, variants, product)
5
5
  @option_types = option_types
6
6
  @variant_ids = variants.map(&:id)
7
+ @product = product
7
8
  end
8
9
 
9
10
  def default_variant
@@ -30,7 +31,7 @@ module Spree
30
31
  return {} if option_types.empty?
31
32
 
32
33
  @default_variant_data ||= begin
33
- find_in_stock_variant_data || find_backorderable_variant_data || find_first_variant_data
34
+ try_default_variant || find_in_stock_variant_data || find_backorderable_variant_data || find_first_variant_data
34
35
  end
35
36
  end
36
37
 
@@ -44,7 +45,17 @@ module Spree
44
45
 
45
46
  def find_variant_data(&block)
46
47
  option_types.first.option_values.each do |option_value|
47
- variant = option_value.variants.where(id: @variant_ids).find(&block)
48
+ variant = option_value.variants.where(id: @variant_ids).order(:position).find(&block)
49
+
50
+ return { variant: variant, option_value: option_value } if variant
51
+ end
52
+
53
+ nil
54
+ end
55
+
56
+ def try_default_variant
57
+ option_types.first.option_values.each do |option_value|
58
+ variant = option_value.variants.where(id: @product.default_variant_id).first
48
59
 
49
60
  return { variant: variant, option_value: option_value } if variant
50
61
  end
@@ -54,7 +65,7 @@ module Spree
54
65
 
55
66
  def find_first_variant_data
56
67
  option_value = option_types.first.option_values.first
57
- variant = option_value.variants.where(id: @variant_ids).first
68
+ variant = option_value.variants.where(id: @variant_ids).order(:position).first
58
69
 
59
70
  { variant: variant, option_value: option_value }
60
71
  end
@@ -65,7 +76,7 @@ module Spree
65
76
  id: option_value.id,
66
77
  position: option_value.position,
67
78
  presentation: option_value.presentation,
68
- variant_id: option_value.variants.where(id: @variant_ids).first.id,
79
+ variant_id: option_value.variants.where(id: @variant_ids).order(:position).first.id,
69
80
  is_default: option_value == default_variant_data[:option_value]
70
81
  }
71
82
  end
@@ -488,7 +488,7 @@ en:
488
488
  add_variant: Add Variant
489
489
  add_store: New Store
490
490
  add_store_credit: Add Store Credit
491
- added_to_cart: Added to bag successfully!
491
+ added_to_cart: Added to cart successfully!
492
492
  additional_item: Additional Item
493
493
  address: Address
494
494
  address1: Address
@@ -636,7 +636,7 @@ en:
636
636
  add_promo_code: ADD PROMO CODE
637
637
  checkout: checkout
638
638
  empty_info: 'Your cart is empty.'
639
- header: Your shopping bag
639
+ header: Your shopping cart
640
640
  product: product
641
641
  quantity: quantity
642
642
  title: Shopping Cart
@@ -1213,7 +1213,7 @@ en:
1213
1213
  not_found_filters2: Please try another choose.
1214
1214
  not_found_text1: We couldn’t find products for '%{keywords}'.
1215
1215
  not_found_text2: Please try another search.
1216
- price: Price
1216
+ price: price
1217
1217
  price_high_to_low: PRICE (HIGH - LOW)
1218
1218
  price_low_to_high: PRICE (LOW - HIGH)
1219
1219
  result: RESULT
@@ -1367,6 +1367,7 @@ en:
1367
1367
  authorized: Authorized
1368
1368
  canceled: Canceled
1369
1369
  return_authorization_updated: Return authorization updated
1370
+ return_authorization_canceled: Return authorization canceled
1370
1371
  return_authorizations: Return Authorizations
1371
1372
  return_item_inventory_unit_ineligible: Return item's inventory unit must be shipped
1372
1373
  return_item_inventory_unit_reimbursed: Return item's inventory unit is already reimbursed
@@ -0,0 +1 @@
1
+ Spree::StoreCreditCategory.find_or_create_by!(name: 'Default')
@@ -1,5 +1,5 @@
1
1
  module Spree
2
2
  def self.version
3
- '4.1.0.rc3'
3
+ '4.1.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0.rc3
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Schofield
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-14 00:00:00.000000000 Z
11
+ date: 2020-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemerchant
@@ -677,6 +677,7 @@ files:
677
677
  - db/default/spree/default_reimbursement_type.rb
678
678
  - db/default/spree/roles.rb
679
679
  - db/default/spree/states.rb
680
+ - db/default/spree/store_credit_categories.rb
680
681
  - db/default/spree/stores.rb
681
682
  - db/default/spree/zones.rb
682
683
  - db/migrate/20120831092320_spree_one_two.rb