spree_core 2.4.0.rc3 → 2.4.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.
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