spree_core 2.4.0.rc3 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/base_helper.rb +1 -1
  3. data/app/models/concerns/spree/default_price.rb +34 -0
  4. data/app/models/spree/asset.rb +1 -1
  5. data/app/models/spree/option_type.rb +3 -1
  6. data/app/models/spree/option_value.rb +2 -1
  7. data/app/models/spree/order.rb +19 -2
  8. data/app/models/spree/order/checkout.rb +4 -0
  9. data/app/models/spree/order_contents.rb +5 -2
  10. data/app/models/spree/payment_method.rb +4 -4
  11. data/app/models/spree/price.rb +2 -18
  12. data/app/models/spree/product.rb +25 -24
  13. data/app/models/spree/promotion/actions/create_item_adjustments.rb +4 -1
  14. data/app/models/spree/promotion/rules/taxon.rb +8 -0
  15. data/app/models/spree/reimbursement.rb +2 -0
  16. data/app/models/spree/return_item.rb +1 -1
  17. data/app/models/spree/return_item/eligibility_validator/base_validator.rb +2 -2
  18. data/app/models/spree/return_item/{default_eligibility_validator.rb → eligibility_validator/default.rb} +1 -1
  19. data/app/models/spree/return_item/exchange_variant_eligibility/same_product.rb +1 -1
  20. data/app/models/spree/variant.rb +17 -38
  21. data/config/locales/en.yml +6 -0
  22. data/db/migrate/20140530024945_move_order_token_from_tokenized_permission.rb +1 -1
  23. data/db/migrate/20141120135441_add_guest_token_index_to_spree_orders.rb +5 -0
  24. data/lib/spree/core.rb +3 -3
  25. data/lib/spree/core/controller_helpers/order.rb +3 -1
  26. data/lib/spree/core/version.rb +1 -1
  27. data/lib/spree/localized_number.rb +20 -0
  28. data/lib/spree/money.rb +2 -2
  29. data/lib/spree/testing_support/factories/options_factory.rb +3 -2
  30. data/lib/spree/testing_support/factories/variant_factory.rb +1 -1
  31. data/lib/tasks/exchanges.rake +2 -2
  32. metadata +12 -10
  33. data/db/development.sqlite +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3ad557fa8765c3b9bd3d6532c913962d33865e28
4
- data.tar.gz: c424bb23636fd0889e52830a5905bb48069e2440
3
+ metadata.gz: 7ed979ffaeda61e053a4b98e9dc25390529f0f0e
4
+ data.tar.gz: 3d4c081a21a8f8a118066c765c0970aa18322c5d
5
5
  SHA512:
6
- metadata.gz: bc7f1a23e33514c7b732f8c154dad4310c7bf3f2a617eabb5b138d97516d6ea0f67edfca2e4e20fc6d59a4bda1ff0a1d37aab2b1f1888b715a8d31ea617faa81
7
- data.tar.gz: f5b67b3fe498f7e92d50cf242df7b9638304563348efd0ff6fbaeedd8bbe653fb971b566224b9d44763c71608d77edecdd652d00728c77face10db1f3aff2d75
6
+ metadata.gz: b919e8bca207687063f08ddda21b392381991e04f409b86d8d32c63e6ee38158a3b0ea5348158f662d52693dbe17b4af3e402cc99c6f1555b2fe61ed94f235d1
7
+ data.tar.gz: d9c59d21c2b5faece11d94a153cdb1bcee54adf364662b20d9b069550067b25629a9403fcf709b5b150633356b925bf41462a0252954951171d0f582c1f3d6e2
@@ -48,7 +48,7 @@ module Spree
48
48
  meta.reverse_merge!({
49
49
  keywords: current_store.meta_keywords,
50
50
  description: current_store.meta_description,
51
- })
51
+ }) if meta[:keywords].blank? or meta[:description].blank?
52
52
  meta
53
53
  end
54
54
 
@@ -0,0 +1,34 @@
1
+ module Spree
2
+ module DefaultPrice
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_one :default_price,
7
+ -> { where currency: Spree::Config[:currency] },
8
+ class_name: 'Spree::Price',
9
+ dependent: :destroy
10
+
11
+ delegate_belongs_to :default_price, :display_price, :display_amount, :price, :price=, :currency
12
+
13
+ after_save :save_default_price
14
+
15
+ def default_price
16
+ Spree::Price.unscoped { super }
17
+ end
18
+
19
+ def has_default_price?
20
+ !self.default_price.nil?
21
+ end
22
+
23
+ private
24
+
25
+ def default_price_changed?
26
+ default_price && (default_price.changed? || default_price.new_record?)
27
+ end
28
+
29
+ def save_default_price
30
+ default_price.save if default_price_changed?
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class Asset < Spree::Base
3
3
  belongs_to :viewable, polymorphic: true, touch: true
4
- acts_as_list scope: :viewable
4
+ acts_as_list scope: [:viewable_id, :viewable_type]
5
5
  end
6
6
  end
@@ -5,7 +5,9 @@ module Spree
5
5
  has_many :products, through: :product_option_types
6
6
  has_and_belongs_to_many :prototypes, join_table: 'spree_option_types_prototypes'
7
7
 
8
- validates :name, :presentation, presence: true
8
+ validates :name, presence: true, uniqueness: true
9
+ validates :presentation, presence: true
10
+
9
11
  default_scope -> { order("#{self.table_name}.position") }
10
12
 
11
13
  accepts_nested_attributes_for :option_values, reject_if: lambda { |ov| ov[:name].blank? || ov[:presentation].blank? }, allow_destroy: true
@@ -4,7 +4,8 @@ module Spree
4
4
  acts_as_list scope: :option_type
5
5
  has_and_belongs_to_many :variants, join_table: 'spree_option_values_variants', class_name: "Spree::Variant"
6
6
 
7
- validates :name, :presentation, presence: true
7
+ validates :name, presence: true, uniqueness: true
8
+ validates :presentation, presence: true
8
9
 
9
10
  after_touch :touch_all_variants
10
11
 
@@ -430,9 +430,26 @@ module Spree
430
430
  line_items.select(&:insufficient_stock?)
431
431
  end
432
432
 
433
+ ##
434
+ # Check to see if any line item variants are soft, deleted.
435
+ # If so add error and restart checkout.
436
+ def ensure_line_item_variants_are_not_deleted
437
+ if line_items.select{ |li| li.variant.destroyed? }.present?
438
+ errors.add(:base, Spree.t(:deleted_variants_present))
439
+ restart_checkout_flow
440
+ false
441
+ else
442
+ true
443
+ end
444
+ end
445
+
433
446
  def ensure_line_items_are_in_stock
434
447
  if insufficient_stock_lines.present?
435
- errors.add(:base, Spree.t(:insufficient_stock_lines_present)) and return false
448
+ errors.add(:base, Spree.t(:insufficient_stock_lines_present))
449
+ restart_checkout_flow
450
+ false
451
+ else
452
+ true
436
453
  end
437
454
  end
438
455
 
@@ -446,7 +463,7 @@ module Spree
446
463
  current_line_item = self.line_items.detect { |my_li|
447
464
  my_li.variant == other_order_line_item.variant &&
448
465
  self.line_item_comparison_hooks.all? { |hook|
449
- self.send(hook, my_li, other_order_line_item)
466
+ self.send(hook, my_li, other_order_line_item.serializable_hash)
450
467
  }
451
468
  }
452
469
  if current_line_item
@@ -99,8 +99,12 @@ module Spree
99
99
  before_transition from: :delivery, do: :apply_free_shipping_promotions
100
100
  end
101
101
 
102
+ before_transition to: :resumed, do: :ensure_line_item_variants_are_not_deleted
102
103
  before_transition to: :resumed, do: :ensure_line_items_are_in_stock
103
104
 
105
+ before_transition to: :complete, do: :ensure_line_item_variants_are_not_deleted
106
+ before_transition to: :complete, do: :ensure_line_items_are_in_stock
107
+
104
108
  after_transition to: :complete, do: :finalize!
105
109
  after_transition to: :resumed, do: :after_resume
106
110
  after_transition to: :canceled, do: :after_cancel
@@ -47,9 +47,12 @@ module Spree
47
47
  filtered_params = params.symbolize_keys
48
48
  return filtered_params if filtered_params[:line_items_attributes].nil? || filtered_params[:line_items_attributes][:id]
49
49
 
50
+ line_item_ids = order.line_items.pluck(:id)
51
+
50
52
  params[:line_items_attributes].each_pair do |id, value|
51
- line_item_id = value[:id]
52
- filtered_params[:line_items_attributes].delete(id) unless Spree::LineItem.find_by_id(line_item_id.to_i)
53
+ unless line_item_ids.include?(value[:id].to_i) || value[:variant_id].present?
54
+ filtered_params[:line_items_attributes].delete(id)
55
+ end
53
56
  end
54
57
  filtered_params
55
58
  end
@@ -16,14 +16,14 @@ module Spree
16
16
  end
17
17
 
18
18
  def provider_class
19
- raise 'You must implement provider_class method for this gateway.'
19
+ raise ::NotImplementedError, 'You must implement provider_class method for this gateway.'
20
20
  end
21
21
 
22
22
  # The class that will process payments for this payment type, used for @payment.source
23
23
  # e.g. CreditCard in the case of a the Gateway payment type
24
24
  # nil means the payment method doesn't require a source e.g. check
25
25
  def payment_source_class
26
- raise 'You must implement payment_source_class method for this gateway.'
26
+ raise ::NotImplementedError, 'You must implement payment_source_class method for this gateway.'
27
27
  end
28
28
 
29
29
  def self.available(display_on = 'both')
@@ -68,8 +68,8 @@ module Spree
68
68
  true
69
69
  end
70
70
 
71
- def cancel
72
- raise NotImplimentedError.new 'You must implement cancel method for this payment method.'
71
+ def cancel(response)
72
+ raise ::NotImplementedError, 'You must implement cancel method for this payment method.'
73
73
  end
74
74
  end
75
75
  end
@@ -21,7 +21,7 @@ module Spree
21
21
  end
22
22
 
23
23
  def price=(price)
24
- self[:amount] = parse_price(price)
24
+ self[:amount] = Spree::LocalizedNumber.parse(price)
25
25
  end
26
26
 
27
27
  # Remove variant default_scope `deleted_at: nil`
@@ -32,23 +32,7 @@ module Spree
32
32
  private
33
33
 
34
34
  def check_price
35
- raise "Price must belong to a variant" if variant.nil?
36
-
37
- if currency.nil?
38
- self.currency = Spree::Config[:currency]
39
- end
40
- end
41
-
42
- # strips all non-price-like characters from the price, taking into account locale settings
43
- def parse_price(price)
44
- return price unless price.is_a?(String)
45
-
46
- separator, delimiter = I18n.t([:'number.currency.format.separator', :'number.currency.format.delimiter'])
47
- non_price_characters = /[^0-9\-#{separator}]/
48
- price.gsub!(non_price_characters, '') # strip everything else first
49
- price.gsub!(separator, '.') unless separator == '.' # then replace the locale-specific decimal separator with the standard separator if necessary
50
-
51
- price.to_d
35
+ self.currency ||= Spree::Config[:currency]
52
36
  end
53
37
 
54
38
  def maximum_amount
@@ -64,32 +64,33 @@ module Spree
64
64
 
65
65
  delegate_belongs_to :master, :cost_price
66
66
 
67
+ delegate :images, to: :master, prefix: true
68
+ alias_method :images, :master_images
69
+
70
+ has_many :variant_images, -> { order(:position) }, source: :images, through: :variants_including_master
71
+
67
72
  after_create :set_master_variant_defaults
68
73
  after_create :add_associations_from_prototype
69
74
  after_create :build_variants_from_option_values_hash, if: :option_values_hash
70
75
 
76
+ after_destroy :punch_slug
77
+
78
+ after_initialize :ensure_master
79
+
71
80
  after_save :save_master
72
81
  after_save :run_touch_callbacks, if: :anything_changed?
73
82
  after_save :reset_nested_changes
74
83
  after_touch :touch_taxons
75
84
 
76
- delegate :images, to: :master, prefix: true
77
- alias_method :images, :master_images
78
-
79
- has_many :variant_images, -> { order(:position) }, source: :images, through: :variants_including_master
85
+ before_validation :normalize_slug, on: :update
86
+ before_validation :validate_master
80
87
 
88
+ validates :meta_keywords, length: { maximum: 255 }
89
+ validates :meta_title, length: { maximum: 255 }
81
90
  validates :name, presence: true
82
91
  validates :price, presence: true, if: proc { Spree::Config[:require_master_price] }
83
92
  validates :shipping_category_id, presence: true
84
- validates :slug, length: { minimum: 3 }
85
-
86
- validates :slug, uniqueness: { allow_blank: true }
87
- validates :meta_keywords, length: { maximum: 255 }
88
- validates :meta_title, length: { maximum: 255 }
89
-
90
- before_validation :normalize_slug, on: :update
91
-
92
- after_destroy :punch_slug
93
+ validates :slug, length: { minimum: 3 }, uniqueness: { allow_blank: true }
93
94
 
94
95
  attr_accessor :option_values_hash
95
96
 
@@ -97,8 +98,6 @@ module Spree
97
98
 
98
99
  alias :options :product_option_types
99
100
 
100
- after_initialize :ensure_master
101
-
102
101
  # the master variant is not a member of the variants array
103
102
  def has_variants?
104
103
  variants.any?
@@ -279,19 +278,21 @@ module Spree
279
278
  # when saving so we force a save using a hook
280
279
  # Fix for issue #5306
281
280
  def save_master
282
- begin
283
- if master && (master.changed? || master.new_record? || (master.default_price && (master.default_price.changed? || master.default_price.new_record?)))
284
- master.save!
285
- @nested_changes = true
286
- end
281
+ if master && (master.changed? || master.new_record? || (master.default_price && (master.default_price.changed? || master.default_price.new_record?)))
282
+ master.save!
283
+ @nested_changes = true
284
+ end
285
+ end
287
286
 
288
- # If the master cannot be saved, the Product object will get its errors
289
- # and will be destroyed
290
- rescue ActiveRecord::RecordInvalid
287
+ # If the master cannot be saved, the Product object will get its errors
288
+ # and will be destroyed
289
+ def validate_master
290
+ # We call master.default_price here to ensure price is initialized.
291
+ # Required to avoid Variant#check_price validation failing on create.
292
+ unless master.default_price && master.valid?
291
293
  master.errors.each do |att, error|
292
294
  self.errors.add(att, error)
293
295
  end
294
- raise
295
296
  end
296
297
  end
297
298
 
@@ -64,7 +64,10 @@ module Spree
64
64
  end
65
65
 
66
66
  def line_items_to_adjust(promotion, order)
67
- excluded_ids = self.adjustments.pluck(:adjustable_id)
67
+ excluded_ids = self.adjustments.
68
+ where(adjustable_id: order.line_items.pluck(:id), adjustable_type: 'Spree::LineItem').
69
+ pluck(:adjustable_id)
70
+
68
71
  order.line_items.where.not(id: excluded_ids).select do |line_item|
69
72
  promotion.line_item_actionable? order, line_item
70
73
  end
@@ -26,6 +26,10 @@ module Spree
26
26
  eligibility_errors.empty?
27
27
  end
28
28
 
29
+ def actionable?(line_item)
30
+ taxon_product_ids.include? line_item.variant.product_id
31
+ end
32
+
29
33
  def taxon_ids_string
30
34
  taxons.pluck(:id).join(',')
31
35
  end
@@ -55,6 +59,10 @@ module Spree
55
59
  def taxons_in_order_including_parents(order)
56
60
  order_taxons_in_taxons_and_children(order).inject([]){ |taxons, taxon| taxons << taxon.self_and_ancestors }.flatten.uniq
57
61
  end
62
+
63
+ def taxon_product_ids
64
+ Spree::Product.joins(:taxons).where(spree_taxons: {id: taxons.pluck(:id)}).pluck(:id).uniq
65
+ end
58
66
  end
59
67
  end
60
68
  end
@@ -17,6 +17,8 @@ module Spree
17
17
 
18
18
  before_create :generate_number
19
19
 
20
+ scope :reimbursed, -> { where(reimbursement_status: 'reimbursed') }
21
+
20
22
  # The reimbursement_tax_calculator property should be set to an object that responds to "call"
21
23
  # and accepts a reimbursement object. Invoking "call" should update the tax fields on the
22
24
  # associated ReturnItems.
@@ -3,7 +3,7 @@ module Spree
3
3
  COMPLETED_RECEPTION_STATUSES = %w(received given_to_customer)
4
4
 
5
5
  class_attribute :return_eligibility_validator
6
- self.return_eligibility_validator = ReturnItem::EligibilityValidator::DefaultEligibilityValidator
6
+ self.return_eligibility_validator = ReturnItem::EligibilityValidator::Default
7
7
 
8
8
  class_attribute :exchange_variant_engine
9
9
  self.exchange_variant_engine = ReturnItem::ExchangeVariantEligibility::SameProduct
@@ -8,11 +8,11 @@ module Spree
8
8
  end
9
9
 
10
10
  def eligible_for_return?
11
- raise 'Implement me'
11
+ raise NotImplementedError, Spree.t(:implement_eligible_for_return)
12
12
  end
13
13
 
14
14
  def requires_manual_intervention?
15
- raise 'Implement me'
15
+ raise NotImplementedError, Spree.t(:implement_requires_manual_intervention)
16
16
  end
17
17
 
18
18
  private
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- class ReturnItem::DefaultEligibilityValidator < Spree::ReturnItem::EligibilityValidator::BaseValidator
2
+ class ReturnItem::EligibilityValidator::Default < Spree::ReturnItem::EligibilityValidator::BaseValidator
3
3
  class_attribute :permitted_eligibility_validators
4
4
  self.permitted_eligibility_validators = [
5
5
  ReturnItem::EligibilityValidator::TimeSincePurchase,
@@ -3,7 +3,7 @@ module Spree
3
3
  class SameProduct
4
4
 
5
5
  def self.eligible_variants(variant)
6
- Spree::Variant.where.not(id: variant.id).where(product_id: variant.product_id, is_master: false)
6
+ Spree::Variant.where(product_id: variant.product_id, is_master: false).in_stock
7
7
  end
8
8
  end
9
9
  end
@@ -2,6 +2,8 @@ module Spree
2
2
  class Variant < Spree::Base
3
3
  acts_as_paranoid
4
4
 
5
+ include Spree::DefaultPrice
6
+
5
7
  belongs_to :product, touch: true, class_name: 'Spree::Product', inverse_of: :variants
6
8
  belongs_to :tax_category, class_name: 'Spree::TaxCategory'
7
9
 
@@ -20,31 +22,27 @@ module Spree
20
22
  has_and_belongs_to_many :option_values, join_table: :spree_option_values_variants
21
23
  has_many :images, -> { order(:position) }, as: :viewable, dependent: :destroy, class_name: "Spree::Image"
22
24
 
23
- has_one :default_price,
24
- -> { where currency: Spree::Config[:currency] },
25
- class_name: 'Spree::Price', inverse_of: :variant
26
-
27
- delegate_belongs_to :default_price, :display_price, :display_amount, :price, :price=, :currency
28
-
29
25
  has_many :prices,
30
26
  class_name: 'Spree::Price',
31
27
  dependent: :destroy,
32
28
  inverse_of: :variant
33
29
 
30
+ before_validation :set_cost_currency
31
+
34
32
  validate :check_price
35
33
 
36
34
  validates :cost_price, numericality: { greater_than_or_equal_to: 0, allow_nil: true }
37
35
  validates :price, numericality: { greater_than_or_equal_to: 0, allow_nil: true }
38
36
  validates_uniqueness_of :sku, allow_blank: true, conditions: -> { where(deleted_at: nil) }
39
37
 
40
- before_validation :set_cost_currency
41
- after_save :save_default_price
42
38
  after_create :create_stock_items
43
39
  after_create :set_position
44
- after_create :set_master_out_of_stock, :unless => :is_master?
40
+ after_create :set_master_out_of_stock, unless: :is_master?
45
41
 
46
42
  after_touch :clear_in_stock_cache
47
43
 
44
+ scope :in_stock, -> { joins(:stock_items).where('count_on_hand > ? OR track_inventory = ?', 0, false) }
45
+
48
46
  def self.active(currency = nil)
49
47
  joins(:prices).where(deleted_at: nil).where('spree_prices.currency' => currency || Spree::Config[:currency]).where('spree_prices.amount IS NOT NULL')
50
48
  end
@@ -58,7 +56,11 @@ module Spree
58
56
  end
59
57
 
60
58
  def cost_price=(price)
61
- self[:cost_price] = parse_price(price) if price.present?
59
+ self[:cost_price] = Spree::LocalizedNumber.parse(price) if price.present?
60
+ end
61
+
62
+ def weight=(weight)
63
+ self[:weight] = Spree::LocalizedNumber.parse(weight) if weight.present?
62
64
  end
63
65
 
64
66
  # returns number of units currently on backorder for this variant.
@@ -66,6 +68,10 @@ module Spree
66
68
  inventory_units.with_state('backordered').size
67
69
  end
68
70
 
71
+ def is_backorderable?
72
+ Spree::Stock::Quantifier.new(self).backorderable?
73
+ end
74
+
69
75
  def options_text
70
76
  values = self.option_values.sort do |a, b|
71
77
  a.option_type.position <=> b.option_type.position
@@ -92,10 +98,6 @@ module Spree
92
98
  Spree::Product.unscoped { super }
93
99
  end
94
100
 
95
- def default_price
96
- Spree::Price.unscoped { super }
97
- end
98
-
99
101
  def options=(options = {})
100
102
  options.each do |option|
101
103
  set_option_value(option[:name], option[:value])
@@ -136,10 +138,6 @@ module Spree
136
138
  self.option_values.detect { |o| o.option_type.name == opt_name }.try(:presentation)
137
139
  end
138
140
 
139
- def has_default_price?
140
- !self.default_price.nil?
141
- end
142
-
143
141
  def price_in(currency)
144
142
  prices.select{ |price| price.currency == currency }.first || Spree::Price.new(variant_id: self.id, currency: currency)
145
143
  end
@@ -167,7 +165,7 @@ module Spree
167
165
  options.keys.map { |key|
168
166
  m = "#{options[key]}_price_modifier_amount".to_sym
169
167
  if self.respond_to? m
170
- self.send(m, options[key])
168
+ self.send(m, options[key])
171
169
  else
172
170
  0
173
171
  end
@@ -203,17 +201,6 @@ module Spree
203
201
  end
204
202
 
205
203
  private
206
- # strips all non-price-like characters from the price, taking into account locale settings
207
- def parse_price(price)
208
- return price unless price.is_a?(String)
209
-
210
- separator, delimiter = I18n.t([:'number.currency.format.separator', :'number.currency.format.delimiter'])
211
- non_price_characters = /[^0-9\-#{separator}]/
212
- price.gsub!(non_price_characters, '') # strip everything else first
213
- price.gsub!(separator, '.') unless separator == '.' # then replace the locale-specific decimal separator with the standard separator if necessary
214
-
215
- price.to_d
216
- end
217
204
 
218
205
  def set_master_out_of_stock
219
206
  if product.master && product.master.in_stock?
@@ -234,14 +221,6 @@ module Spree
234
221
  end
235
222
  end
236
223
 
237
- def default_price_changed?
238
- default_price && (default_price.changed? || default_price.new_record?)
239
- end
240
-
241
- def save_default_price
242
- default_price.save if default_price_changed?
243
- end
244
-
245
224
  def set_cost_currency
246
225
  self.cost_currency = Spree::Config[:currency] if cost_currency.nil? || cost_currency.empty?
247
226
  end
@@ -528,6 +528,9 @@ en:
528
528
  choose_dashboard_locale: Choose Dashboard Locale
529
529
  choose_location: Choose location
530
530
  city: City
531
+ clear_cache: Clear Cache
532
+ clear_cache_ok: Cache was flushed
533
+ clear_cache_warning: Clearing cache will temporarily reduce the performance of your store.
531
534
  click_and_drag_on_the_products_to_sort_them: Click and drag on the products to sort them.
532
535
  clone: Clone
533
536
  close: Close
@@ -614,6 +617,7 @@ en:
614
617
  default_tax: Default Tax
615
618
  default_tax_zone: Default Tax Zone
616
619
  delete: Delete
620
+ deleted_variants_present: Some line items in this order have products that are no longer available.
617
621
  delivery: Delivery
618
622
  depth: Depth
619
623
  description: Description
@@ -833,6 +837,8 @@ en:
833
837
  month: Month
834
838
  more: More
835
839
  move_stock_between_locations: Move Stock Between Locations
840
+ must_implement_eligible_for_return: "Must implement #eligible_for_return? for your EligibilityValidator."
841
+ must_implement_requires_manual_intervention: "Must implement #requires_manual_intervention? for your EligibilityValidator."
836
842
  my_account: My Account
837
843
  my_orders: My Orders
838
844
  name: Name
@@ -10,7 +10,7 @@ class MoveOrderTokenFromTokenizedPermission < ActiveRecord::Migration
10
10
  Spree::Order.includes(:tokenized_permission).each do |o|
11
11
  o.update_column :guest_token, o.tokenized_permission.token
12
12
  end
13
- when 'Mysql2'
13
+ when 'Mysql2', 'MySQL'
14
14
  execute "UPDATE spree_orders, spree_tokenized_permissions
15
15
  SET spree_orders.guest_token = spree_tokenized_permissions.token
16
16
  WHERE spree_tokenized_permissions.permissable_id = spree_orders.id
@@ -0,0 +1,5 @@
1
+ class AddGuestTokenIndexToSpreeOrders < ActiveRecord::Migration
2
+ def change
3
+ add_index :spree_orders, :guest_token
4
+ end
5
+ end
data/lib/spree/core.rb CHANGED
@@ -58,10 +58,12 @@ require 'spree/migrations'
58
58
  require 'spree/core/engine'
59
59
 
60
60
  require 'spree/i18n'
61
+ require 'spree/localized_number'
61
62
  require 'spree/money'
62
-
63
63
  require 'spree/permitted_attributes'
64
+
64
65
  require 'spree/core/delegate_belongs_to'
66
+ require 'spree/core/importer'
65
67
  require 'spree/core/permalinks'
66
68
  require 'spree/core/product_duplicator'
67
69
  require 'spree/core/controller_helpers/auth'
@@ -73,8 +75,6 @@ require 'spree/core/controller_helpers/ssl'
73
75
  require 'spree/core/controller_helpers/store'
74
76
  require 'spree/core/controller_helpers/strong_parameters'
75
77
 
76
- require 'spree/core/importer'
77
-
78
78
  # Hack waiting on https://github.com/pluginaweek/state_machine/pull/275
79
79
  module StateMachine
80
80
  module Integrations
@@ -22,13 +22,14 @@ module Spree
22
22
  if @simple_current_order
23
23
  @simple_current_order.last_ip_address = ip_address
24
24
  return @simple_current_order
25
+ else
26
+ @simple_current_order = Spree::Order.new
25
27
  end
26
28
  end
27
29
 
28
30
  # The current incomplete order from the guest_token for use in cart and during checkout
29
31
  def current_order(options = {})
30
32
  options[:create_order_if_necessary] ||= false
31
- options[:lock] ||= false
32
33
 
33
34
  return @current_order if @current_order
34
35
 
@@ -82,6 +83,7 @@ module Spree
82
83
  end
83
84
 
84
85
  def find_order_by_token_or_user(options={}, with_adjustments = false)
86
+ options[:lock] ||= false
85
87
 
86
88
  # Find any incomplete orders for the guest_token
87
89
  if with_adjustments
@@ -1,5 +1,5 @@
1
1
  module Spree
2
2
  def self.version
3
- "2.4.0.rc3"
3
+ "2.4.0"
4
4
  end
5
5
  end
@@ -0,0 +1,20 @@
1
+ module Spree
2
+ class LocalizedNumber
3
+
4
+ # Strips all non-price-like characters from the number, taking into account locale settings.
5
+ def self.parse(number)
6
+ return number unless number.is_a?(String)
7
+
8
+ separator, delimiter = I18n.t([:'number.currency.format.separator', :'number.currency.format.delimiter'])
9
+ non_number_characters = /[^0-9\-#{separator}]/
10
+
11
+ # strip everything else first
12
+ number.gsub!(non_number_characters, '')
13
+ # then replace the locale-specific decimal separator with the standard separator if necessary
14
+ number.gsub!(separator, '.') unless separator == '.'
15
+
16
+ number.to_d
17
+ end
18
+
19
+ end
20
+ end
data/lib/spree/money.rb CHANGED
@@ -6,7 +6,7 @@ module Spree
6
6
  class Money
7
7
  attr_reader :money
8
8
 
9
- delegate :cents, :to => :money
9
+ delegate :cents, to: :money
10
10
 
11
11
  def initialize(amount, options={})
12
12
  @money = Monetize.parse([amount, (options[:currency] || Spree::Config[:currency])].join)
@@ -26,7 +26,7 @@ module Spree
26
26
  @money.format(@options)
27
27
  end
28
28
 
29
- def to_html(options = { :html => true })
29
+ def to_html(options = { html: true })
30
30
  output = @money.format(@options.merge(options))
31
31
  if options[:html]
32
32
  # 1) prevent blank, breaking spaces
@@ -1,12 +1,13 @@
1
1
  FactoryGirl.define do
2
2
  factory :option_value, class: Spree::OptionValue do
3
- name 'Size'
3
+ sequence(:name) { |n| "Size-#{n}" }
4
+
4
5
  presentation 'S'
5
6
  option_type
6
7
  end
7
8
 
8
9
  factory :option_type, class: Spree::OptionType do
9
- name 'foo-size'
10
+ sequence(:name) { |n| "foo-size-#{n}" }
10
11
  presentation 'Size'
11
12
  end
12
13
  end
@@ -4,7 +4,7 @@ FactoryGirl.define do
4
4
  factory :base_variant, class: Spree::Variant do
5
5
  price 19.99
6
6
  cost_price 17.00
7
- sku { generate(:sku) }
7
+ sku { generate(:sku) }
8
8
  weight { generate(:random_float) }
9
9
  height { generate(:random_float) }
10
10
  width { generate(:random_float) }
@@ -4,8 +4,8 @@ namespace :exchanges do
4
4
  task charge_unreturned_items: :environment do
5
5
 
6
6
  unreturned_return_items = Spree::ReturnItem.awaiting_return.exchange_processed.joins(:exchange_inventory_unit).where([
7
- "spree_inventory_units.created_at < :days_ago",
8
- days_ago: Spree::Config[:expedited_exchanges_days_window].days.ago
7
+ "spree_inventory_units.created_at < :days_ago AND spree_inventory_units.state = :iu_state",
8
+ days_ago: Spree::Config[:expedited_exchanges_days_window].days.ago, iu_state: "shipped"
9
9
  ]).to_a
10
10
 
11
11
  # Determine that a return item has already been deemed unreturned and therefore charged
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: 2.4.0.rc3
4
+ version: 2.4.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: 2014-11-07 00:00:00.000000000 Z
11
+ date: 2014-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemerchant
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 3.0.0.rc.3
47
+ version: 3.0.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 3.0.0.rc.3
54
+ version: 3.0.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: carmen
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -260,14 +260,14 @@ dependencies:
260
260
  requirements:
261
261
  - - "~>"
262
262
  - !ruby/object:Gem::Version
263
- version: 4.1.6
263
+ version: 4.1.8
264
264
  type: :runtime
265
265
  prerelease: false
266
266
  version_requirements: !ruby/object:Gem::Requirement
267
267
  requirements:
268
268
  - - "~>"
269
269
  - !ruby/object:Gem::Version
270
- version: 4.1.6
270
+ version: 4.1.8
271
271
  - !ruby/object:Gem::Dependency
272
272
  name: ransack
273
273
  requirement: !ruby/object:Gem::Requirement
@@ -379,6 +379,7 @@ files:
379
379
  - app/mailers/spree/test_mailer.rb
380
380
  - app/models/concerns/spree/adjustment_source.rb
381
381
  - app/models/concerns/spree/calculated_adjustments.rb
382
+ - app/models/concerns/spree/default_price.rb
382
383
  - app/models/concerns/spree/named_type.rb
383
384
  - app/models/concerns/spree/user_address.rb
384
385
  - app/models/concerns/spree/user_api_authentication.rb
@@ -489,8 +490,8 @@ files:
489
490
  - app/models/spree/return_authorization.rb
490
491
  - app/models/spree/return_authorization_reason.rb
491
492
  - app/models/spree/return_item.rb
492
- - app/models/spree/return_item/default_eligibility_validator.rb
493
493
  - app/models/spree/return_item/eligibility_validator/base_validator.rb
494
+ - app/models/spree/return_item/eligibility_validator/default.rb
494
495
  - app/models/spree/return_item/eligibility_validator/rma_required.rb
495
496
  - app/models/spree/return_item/eligibility_validator/time_since_purchase.rb
496
497
  - app/models/spree/return_item/exchange_variant_eligibility/same_option_value.rb
@@ -560,7 +561,6 @@ files:
560
561
  - db/default/spree/states.rb
561
562
  - db/default/spree/stores.rb
562
563
  - db/default/spree/zones.rb
563
- - db/development.sqlite
564
564
  - db/migrate/20120831092320_spree_one_two.rb
565
565
  - db/migrate/20120831092359_spree_promo_one_two.rb
566
566
  - db/migrate/20120905145253_add_tax_rate_label.rb
@@ -750,6 +750,7 @@ files:
750
750
  - db/migrate/20141023005240_add_counter_cache_from_spree_variants_to_spree_stock_items.rb
751
751
  - db/migrate/20141101231208_fix_adjustment_order_presence.rb
752
752
  - db/migrate/20141105213646_update_classifications_positions.rb
753
+ - db/migrate/20141120135441_add_guest_token_index_to_spree_orders.rb
753
754
  - db/seeds.rb
754
755
  - lib/generators/spree/custom_user/custom_user_generator.rb
755
756
  - lib/generators/spree/custom_user/templates/authentication_helpers.rb.tt
@@ -797,6 +798,7 @@ files:
797
798
  - lib/spree/i18n.rb
798
799
  - lib/spree/i18n/base.rb
799
800
  - lib/spree/i18n/initializer.rb
801
+ - lib/spree/localized_number.rb
800
802
  - lib/spree/migrations.rb
801
803
  - lib/spree/money.rb
802
804
  - lib/spree/permitted_attributes.rb
@@ -884,9 +886,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
884
886
  version: 1.9.3
885
887
  required_rubygems_version: !ruby/object:Gem::Requirement
886
888
  requirements:
887
- - - ">"
889
+ - - ">="
888
890
  - !ruby/object:Gem::Version
889
- version: 1.3.1
891
+ version: '0'
890
892
  requirements: []
891
893
  rubyforge_project:
892
894
  rubygems_version: 2.2.2
File without changes