spree_core 2.4.7 → 2.4.8

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
  SHA1:
3
- metadata.gz: 6e70453c69a40765c3da043aaa45500faf53a473
4
- data.tar.gz: 7f7d4d3f6d687e4ca780d632db70944a51ec4a17
3
+ metadata.gz: 7a4b6e2afb0968da8792da3d641cde6a8628eb48
4
+ data.tar.gz: c2c33ca5c66f6f1c4f2165b4e388f14d82884e91
5
5
  SHA512:
6
- metadata.gz: 6cb8f296090b301cef84ba89770fb22df0bccb7a5d6e6baab595adb07e607d181d7608db28d8f29f820d5fe6ead85e5bc71411e523f31f6b296ad2e5e725a004
7
- data.tar.gz: 1fd7c088dc684dd038214c82eee41278b4fd18ce874570adb45532fbe918a9c69bcb110e3628585975e66555f32ce93295026c6ba2f321baa3fb9f75dd95171c
6
+ metadata.gz: d115ad863b2eecbf62c10eca8635ad099eef6ed3228da587d6b17238e5f1da29664d7eea5ecca3fc579f599c697147d1d097f657bd1e9a0e7e02e44d80944931
7
+ data.tar.gz: 3999bfb8c5830d8ecdfccc20fa5921a4e358ee925348f71611c66272683526cdbe57ab9207c327471f50bb40e839d12f143859d1c9bda97bd6c17caaa7a87de1
@@ -0,0 +1,3 @@
1
+ FriendlyId::Slug.class_eval do
2
+ acts_as_paranoid
3
+ end
@@ -24,7 +24,7 @@ module Spree
24
24
  class Adjustment < Spree::Base
25
25
  belongs_to :adjustable, polymorphic: true, touch: true
26
26
  belongs_to :source, polymorphic: true
27
- belongs_to :order, class_name: "Spree::Order"
27
+ belongs_to :order, class_name: 'Spree::Order', inverse_of: :all_adjustments
28
28
 
29
29
  validates :adjustable, presence: true
30
30
  validates :order, presence: true
@@ -1,5 +1,10 @@
1
1
  module Spree
2
2
  class Calculator < Spree::Base
3
+ # Conditional check for backwards compatibilty since acts as paranoid was added late https://github.com/spree/spree/issues/5858
4
+ if connection.table_exists?(:spree_calculators) && connection.column_exists?(:spree_calculators, :deleted_at)
5
+ acts_as_paranoid
6
+ end
7
+
3
8
  belongs_to :calculable, polymorphic: true
4
9
 
5
10
  # This method calls a compute_<computable> method. must be overriden in concrete calculator.
@@ -2,21 +2,27 @@ module Spree
2
2
  class CustomerReturn < Spree::Base
3
3
  belongs_to :stock_location
4
4
 
5
- has_many :return_items, inverse_of: :customer_return
6
- has_many :return_authorizations, through: :return_items
7
5
  has_many :reimbursements, inverse_of: :customer_return
6
+ has_many :return_authorizations, through: :return_items
7
+ has_many :return_items, inverse_of: :customer_return
8
8
 
9
9
  after_create :process_return!
10
10
  before_create :generate_number
11
11
 
12
12
  validates :return_items, presence: true
13
13
  validates :stock_location, presence: true
14
+
15
+ validate :must_have_return_authorization, on: :create
14
16
  validate :return_items_belong_to_same_order
15
17
 
16
18
  accepts_nested_attributes_for :return_items
17
19
 
18
- def pre_tax_total
19
- return_items.sum(:pre_tax_amount)
20
+ def completely_decided?
21
+ !return_items.undecided.exists?
22
+ end
23
+
24
+ def fully_reimbursed?
25
+ completely_decided? && return_items.accepted.includes(:reimbursement).all? { |return_item| return_item.reimbursement.try(:reimbursed?) }
20
26
  end
21
27
 
22
28
  def display_pre_tax_total
@@ -33,15 +39,21 @@ module Spree
33
39
  order.try(:id)
34
40
  end
35
41
 
36
- def fully_reimbursed?
37
- completely_decided? && return_items.accepted.includes(:reimbursement).all? { |return_item| return_item.reimbursement.try(:reimbursed?) }
42
+ def pre_tax_total
43
+ return_items.sum(:pre_tax_amount)
38
44
  end
39
45
 
40
- def completely_decided?
41
- !return_items.undecided.exists?
46
+ private
47
+
48
+ def inventory_units
49
+ return_items.flat_map(&:inventory_unit)
42
50
  end
43
51
 
44
- private
52
+ def must_have_return_authorization
53
+ if item = return_items.find { |ri| ri.return_authorization.blank? }
54
+ errors.add(:base, Spree.t(:missing_return_authorization, item_name: item.inventory_unit.variant.name))
55
+ end
56
+ end
45
57
 
46
58
  def generate_number
47
59
  self.number ||= loop do
@@ -56,15 +68,9 @@ module Spree
56
68
  end
57
69
 
58
70
  def return_items_belong_to_same_order
59
- if return_items.select{ |return_item| return_item.inventory_unit.order_id != order_id }.any?
71
+ if return_items.select { |return_item| return_item.inventory_unit.order_id != order_id }.any?
60
72
  errors.add(:base, Spree.t(:return_items_cannot_be_associated_with_multiple_orders))
61
73
  end
62
74
  end
63
-
64
- def inventory_units
65
- return_items.flat_map(&:inventory_unit)
66
- end
67
-
68
75
  end
69
76
  end
70
-
@@ -60,6 +60,10 @@ module Spree
60
60
  ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, :test => true, :authorization => '12345')
61
61
  end
62
62
 
63
+ def cancel(_response_code)
64
+ ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345')
65
+ end
66
+
63
67
  def test?
64
68
  # Test mode is not really relevant with bogus gateway (no such thing as live server)
65
69
  true
@@ -44,7 +44,7 @@ module Spree
44
44
  alias_attribute :ship_total, :shipment_total
45
45
 
46
46
  belongs_to :store, class_name: 'Spree::Store'
47
- has_many :state_changes, as: :stateful
47
+ has_many :state_changes, as: :stateful, dependent: :destroy
48
48
  has_many :line_items, -> { order("#{LineItem.table_name}.created_at ASC") }, dependent: :destroy, inverse_of: :order
49
49
  has_many :payments, dependent: :destroy
50
50
  has_many :return_authorizations, dependent: :destroy, inverse_of: :order
@@ -56,6 +56,11 @@ module Spree
56
56
  has_many :products, through: :variants
57
57
  has_many :variants, through: :line_items
58
58
  has_many :refunds, through: :payments
59
+ has_many :all_adjustments,
60
+ class_name: 'Spree::Adjustment',
61
+ foreign_key: :order_id,
62
+ dependent: :destroy,
63
+ inverse_of: :order
59
64
 
60
65
  has_and_belongs_to_many :promotions, join_table: 'spree_orders_promotions'
61
66
 
@@ -90,6 +95,7 @@ module Spree
90
95
  make_permalink field: :number
91
96
 
92
97
  delegate :update_totals, :persist_totals, :to => :updater
98
+ delegate :merge!, to: :merger
93
99
 
94
100
  class_attribute :update_hooks
95
101
  self.update_hooks = Set.new
@@ -135,11 +141,6 @@ module Spree
135
141
  self.line_item_comparison_hooks.add(hook)
136
142
  end
137
143
 
138
- def all_adjustments
139
- Adjustment.where("order_id = :order_id OR (adjustable_id = :order_id AND adjustable_type = 'Spree::Order')",
140
- order_id: self.id)
141
- end
142
-
143
144
  # For compatiblity with Calculator::PriceSack
144
145
  def amount
145
146
  line_items.inject(0.0) { |sum, li| sum + li.amount }
@@ -245,6 +246,10 @@ module Spree
245
246
  updater.update
246
247
  end
247
248
 
249
+ def merger
250
+ @merger ||= Spree::OrderMerger.new(self)
251
+ end
252
+
248
253
  def clone_billing_address
249
254
  if bill_address and self.ship_address.nil?
250
255
  self.ship_address = bill_address.clone
@@ -444,10 +449,10 @@ module Spree
444
449
  end
445
450
 
446
451
  ##
447
- # Check to see if any line item variants are soft, deleted.
452
+ # Check to see if any line item variants are soft deleted.
448
453
  # If so add error and restart checkout.
449
454
  def ensure_line_item_variants_are_not_deleted
450
- if line_items.select{ |li| li.variant.destroyed? }.present?
455
+ if line_items.any?{ |li| !li.variant || li.variant.paranoia_destroyed? }
451
456
  errors.add(:base, Spree.t(:deleted_variants_present))
452
457
  restart_checkout_flow
453
458
  false
@@ -466,44 +471,12 @@ module Spree
466
471
  end
467
472
  end
468
473
 
469
- def merge!(order, user = nil)
470
- order.line_items.each do |other_order_line_item|
471
- next unless other_order_line_item.currency == currency
472
-
473
- # Compare the line items of the other order with mine.
474
- # Make sure you allow any extensions to chime in on whether or
475
- # not the extension-specific parts of the line item match
476
- current_line_item = self.line_items.detect { |my_li|
477
- my_li.variant == other_order_line_item.variant &&
478
- self.line_item_comparison_hooks.all? { |hook|
479
- self.send(hook, my_li, other_order_line_item.serializable_hash)
480
- }
481
- }
482
- if current_line_item
483
- current_line_item.quantity += other_order_line_item.quantity
484
- current_line_item.save!
485
- else
486
- other_order_line_item.order_id = self.id
487
- other_order_line_item.save!
488
- end
489
- end
490
-
491
- self.associate_user!(user) if !self.user && !user.blank?
492
-
493
- updater.update_item_count
494
- updater.update_item_total
495
- updater.persist_totals
496
-
497
- # So that the destroy doesn't take out line items which may have been re-assigned
498
- order.line_items.reload
499
- order.destroy
500
- end
501
-
502
474
  def empty!
503
475
  line_items.destroy_all
504
476
  updater.update_item_count
505
477
  adjustments.destroy_all
506
478
  shipments.destroy_all
479
+ state_changes.destroy_all
507
480
 
508
481
  update_totals
509
482
  persist_totals
@@ -22,10 +22,10 @@ module Spree
22
22
  # Update totals, then check if the order is eligible for any cart promotions.
23
23
  # If we do not update first, then the item total will be wrong and ItemTotal
24
24
  # promotion rules would not be triggered.
25
- reload_totals
25
+ persist_totals
26
26
  PromotionHandler::Cart.new(order).activate
27
27
  order.ensure_updated_shipments
28
- reload_totals
28
+ persist_totals
29
29
  true
30
30
  else
31
31
  false
@@ -34,12 +34,12 @@ module Spree
34
34
 
35
35
  private
36
36
  def after_add_or_remove(line_item, options = {})
37
- reload_totals
37
+ persist_totals
38
38
  shipment = options[:shipment]
39
39
  shipment.present? ? shipment.update_amounts : order.ensure_updated_shipments
40
40
  PromotionHandler::Cart.new(order, line_item).activate
41
41
  ItemAdjustments.new(line_item).update
42
- reload_totals
42
+ persist_totals
43
43
  line_item
44
44
  end
45
45
 
@@ -61,10 +61,9 @@ module Spree
61
61
  @updater ||= OrderUpdater.new(order)
62
62
  end
63
63
 
64
- def reload_totals
64
+ def persist_totals
65
65
  order_updater.update_item_count
66
66
  order_updater.update
67
- order.reload
68
67
  end
69
68
 
70
69
  def add_to_line_item(variant, quantity, options = {})
@@ -90,8 +89,8 @@ module Spree
90
89
  line_item.quantity -= quantity
91
90
  line_item.target_shipment= options[:shipment]
92
91
 
93
- if line_item.quantity == 0
94
- line_item.destroy
92
+ if line_item.quantity.zero?
93
+ order.line_items.destroy(line_item)
95
94
  else
96
95
  line_item.save!
97
96
  end
@@ -0,0 +1,65 @@
1
+ module Spree
2
+ class OrderMerger
3
+ attr_accessor :order
4
+ delegate :updater, to: :order
5
+
6
+ def initialize(order)
7
+ @order = order
8
+ end
9
+
10
+ def merge!(other_order, user = nil)
11
+ other_order.line_items.each do |other_order_line_item|
12
+ next unless other_order_line_item.currency == order.currency
13
+
14
+ current_line_item = find_matching_line_item(other_order_line_item)
15
+ handle_merge(current_line_item, other_order_line_item)
16
+ end
17
+
18
+ set_user(user)
19
+ persist_merge
20
+
21
+ # So that the destroy doesn't take out line items which may have been re-assigned
22
+ other_order.line_items.reload
23
+ other_order.destroy
24
+ end
25
+
26
+ # Compare the line item of the other order with mine.
27
+ # Make sure you allow any extensions to chime in on whether or
28
+ # not the extension-specific parts of the line item match
29
+ def find_matching_line_item(other_order_line_item)
30
+ order.line_items.detect do |my_li|
31
+ my_li.variant == other_order_line_item.variant &&
32
+ order.line_item_comparison_hooks.all? do |hook|
33
+ order.send(hook, my_li, other_order_line_item.serializable_hash)
34
+ end
35
+ end
36
+ end
37
+
38
+ def set_user(user = nil)
39
+ order.associate_user!(user) if !order.user && !user.blank?
40
+ end
41
+
42
+ # The idea is the end developer can choose to override the merge
43
+ # to their own choosing. Default is merge with errors.
44
+ def handle_merge(current_line_item, other_order_line_item)
45
+ if current_line_item
46
+ current_line_item.quantity += other_order_line_item.quantity
47
+ handle_error(current_line_item) unless current_line_item.save
48
+ else
49
+ other_order_line_item.order_id = order.id
50
+ handle_error(other_order_line_item) unless other_order_line_item.save
51
+ end
52
+ end
53
+
54
+ # Change the error messages as you choose.
55
+ def handle_error(line_item)
56
+ order.errors[:base] << line_item.errors.full_messages
57
+ end
58
+
59
+ def persist_merge
60
+ updater.update_item_count
61
+ updater.update_item_total
62
+ updater.persist_totals
63
+ end
64
+ end
65
+ end
@@ -168,10 +168,5 @@ module Spree
168
168
  order.state_changed('payment') if last_state != order.payment_state
169
169
  order.payment_state
170
170
  end
171
-
172
- private
173
- def round_money(n)
174
- (n * 100).round / 100.0
175
- end
176
171
  end
177
172
  end
@@ -16,6 +16,7 @@ module Spree
16
16
  has_many :capture_events, :class_name => 'Spree::PaymentCaptureEvent'
17
17
  has_many :refunds, inverse_of: :payment
18
18
 
19
+ validates_presence_of :payment_method
19
20
  before_validation :validate_source
20
21
  before_create :set_unique_identifier
21
22
 
@@ -164,6 +165,10 @@ module Spree
164
165
  amount - captured_amount
165
166
  end
166
167
 
168
+ def editable?
169
+ checkout? || pending?
170
+ end
171
+
167
172
  private
168
173
 
169
174
  def validate_source
@@ -65,7 +65,8 @@ module Spree
65
65
  end
66
66
 
67
67
  def cancel!
68
- payment_method.cancel(response_code)
68
+ response = payment_method.cancel(response_code)
69
+ handle_response(response, :void, :failure)
69
70
  end
70
71
 
71
72
  def gateway_options
@@ -74,6 +74,7 @@ module Spree
74
74
  after_create :build_variants_from_option_values_hash, if: :option_values_hash
75
75
 
76
76
  after_destroy :punch_slug
77
+ after_restore :update_slug_history
77
78
 
78
79
  after_initialize :ensure_master
79
80
 
@@ -263,7 +264,12 @@ module Spree
263
264
  end
264
265
 
265
266
  def punch_slug
266
- update_column :slug, "#{Time.now.to_i}_#{slug}" # punch slug with date prefix to allow reuse of original
267
+ # punch slug with date prefix to allow reuse of original
268
+ update_column :slug, "#{Time.now.to_i}_#{slug}"[0..254] unless frozen?
269
+ end
270
+
271
+ def update_slug_history
272
+ self.save!
267
273
  end
268
274
 
269
275
  def anything_changed?
@@ -29,22 +29,26 @@ module Spree
29
29
  end
30
30
 
31
31
  private
32
- def promotions
33
- promo_table = Promotion.arel_table
34
- join_table = Arel::Table.new(:spree_orders_promotions)
35
32
 
36
- join_condition = promo_table.join(join_table, Arel::Nodes::OuterJoin).on(
37
- promo_table[:id].eq(join_table[:promotion_id])
38
- ).join_sources
33
+ def promotions
34
+ # AR cannot bind raw ASTs to prepared statements. There always must be a manager around.
35
+ # Also Postgresql requires an aliased table for `SELECT * FROM (subexpression) AS alias`.
36
+ # And Sqlite3 cannot work on outher parenthesis from `(left UNION right)`.
37
+ # So this construct makes both happy.
38
+ select = Arel::SelectManager.new(
39
+ Promotion,
40
+ Promotion.arel_table.create_table_alias(
41
+ order.promotions.active.union(Promotion.active.where(code: nil, path: nil)),
42
+ Promotion.table_name
43
+ ),
44
+ )
45
+ select.project(Arel.star)
39
46
 
40
- Promotion.active.includes(:promotion_rules).
41
- joins(join_condition).
42
- where(
43
- promo_table[:code].eq(nil).and(
44
- promo_table[:path].eq(nil)
45
- ).or(join_table[:order_id].eq(order.id))
46
- ).distinct
47
- end
47
+ Promotion.find_by_sql(
48
+ select,
49
+ order.promotions.bind_values
50
+ )
51
+ end
48
52
  end
49
53
  end
50
54
  end
@@ -86,7 +86,7 @@ module Spree
86
86
  }
87
87
 
88
88
  # Check for applied adjustments.
89
- discount = order.line_item_adjustments.promotion.detect(&detector)
89
+ discount = order.line_item_adjustments.promotion.eligible.detect(&detector)
90
90
  discount ||= order.shipment_adjustments.promotion.detect(&detector)
91
91
  discount ||= order.adjustments.promotion.detect(&detector)
92
92
 
@@ -161,7 +161,7 @@ module Spree
161
161
  end
162
162
 
163
163
  def item_cost
164
- line_items.map(&:final_amount).sum
164
+ manifest.map { |m| (m.line_item.price + (m.line_item.adjustment_total / m.line_item.quantity)) * m.quantity }.sum
165
165
  end
166
166
 
167
167
  def line_items
@@ -5,16 +5,20 @@ module Spree
5
5
  unit_count = line_item.inventory_units.size
6
6
  return if unit_count >= line_item.quantity
7
7
  quantity = line_item.quantity - unit_count
8
+ return if quantity.zero?
8
9
 
9
10
  quantifier = Stock::Quantifier.new(line_item.variant)
10
11
 
11
- unless quantifier.can_supply? quantity
12
- variant = line_item.variant
13
- display_name = %Q{#{variant.name}}
14
- display_name += %Q{ (#{variant.options_text})} unless variant.options_text.blank?
12
+ return if quantifier.can_supply?(quantity)
15
13
 
16
- line_item.errors[:quantity] << Spree.t(:selected_quantity_not_available, :scope => :order_populator, :item => display_name.inspect)
17
- end
14
+ variant = line_item.variant
15
+ display_name = "#{variant.name}"
16
+ display_name += " (#{variant.options_text})" unless variant.options_text.blank?
17
+
18
+ line_item.errors[:quantity] << Spree.t(
19
+ :selected_quantity_not_available,
20
+ item: display_name.inspect
21
+ )
18
22
  end
19
23
  end
20
24
  end
@@ -8,7 +8,11 @@ module Spree
8
8
 
9
9
  validates_presence_of :stock_location, :variant
10
10
  validates_uniqueness_of :variant_id, scope: [:stock_location_id, :deleted_at]
11
- validates :count_on_hand, numericality: { greater_than_or_equal_to: 0 }, if: :verify_count_on_hand?
11
+
12
+ validates_numericality_of :count_on_hand,
13
+ greater_than_or_equal_to: 0,
14
+ less_than_or_equal_to: 2**31 - 1,
15
+ only_integer: true, if: :verify_count_on_hand?
12
16
 
13
17
  delegate :weight, :should_track_inventory?, to: :variant
14
18
 
@@ -6,7 +6,12 @@ module Spree
6
6
  after_create :update_stock_item_quantity
7
7
 
8
8
  validates :stock_item, presence: true
9
- validates :quantity, presence: true
9
+ validates :quantity, presence: true, numericality: {
10
+ greater_than_or_equal_to: -2**31,
11
+ less_than_or_equal_to: 2**31-1,
12
+ only_integer: true,
13
+ allow_nil: true
14
+ }
10
15
 
11
16
  scope :recent, -> { order('created_at DESC') }
12
17
 
@@ -79,7 +79,11 @@ module Spree
79
79
  rates = self.match(order_tax_zone)
80
80
  tax_categories = rates.map(&:tax_category)
81
81
  relevant_items, non_relevant_items = items.partition { |item| tax_categories.include?(item.tax_category) }
82
- Spree::Adjustment.where(adjustable: relevant_items).tax.destroy_all # using destroy_all to ensure adjustment destroy callback fires.
82
+
83
+ if relevant_items.present?
84
+ Spree::Adjustment.where(adjustable: relevant_items).tax.destroy_all # using destroy_all to ensure adjustment destroy callback fires.
85
+ end
86
+
83
87
  relevant_items.each do |item|
84
88
  relevant_rates = rates.select { |rate| rate.tax_category == item.tax_category }
85
89
  store_pre_tax_amount(item, relevant_rates)
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class Variant < Spree::Base
3
3
  acts_as_paranoid
4
- acts_as_list
4
+ acts_as_list scope: :product
5
5
 
6
6
  include Spree::DefaultPrice
7
7
 
@@ -37,7 +37,6 @@ module Spree
37
37
  validates_uniqueness_of :sku, allow_blank: true, conditions: -> { where(deleted_at: nil) }
38
38
 
39
39
  after_create :create_stock_items
40
- after_create :set_position
41
40
  after_create :set_master_out_of_stock, unless: :is_master?
42
41
 
43
42
  after_touch :clear_in_stock_cache
@@ -245,10 +244,6 @@ module Spree
245
244
  end
246
245
  end
247
246
 
248
- def set_position
249
- self.update_column(:position, product.variants.maximum(:position).to_i + 1)
250
- end
251
-
252
247
  def in_stock_cache_key
253
248
  "variant-#{id}-in_stock"
254
249
  end
@@ -23,6 +23,10 @@ Spree::Core::Engine.config.to_prepare do
23
23
  def last_incomplete_spree_order
24
24
  spree_orders.incomplete.order('created_at DESC').first
25
25
  end
26
+
27
+ def analytics_id
28
+ id
29
+ end
26
30
  end
27
31
  end
28
32
  end
@@ -842,6 +842,7 @@ en:
842
842
  meta_title: Meta Title
843
843
  metadata: Metadata
844
844
  minimal_amount: Minimal Amount
845
+ missing_return_authorization: ! 'Missing Return Authorization for %{item_name}.'
845
846
  month: Month
846
847
  more: More
847
848
  move_stock_between_locations: Move Stock Between Locations
@@ -979,7 +980,6 @@ en:
979
980
  order_total: Order Total
980
981
  order_updated: Order Updated
981
982
  orders: Orders
982
- other_items_in_other: Other Items in Order
983
983
  out_of_stock: Out of Stock
984
984
  overview: Overview
985
985
  package_from: package from
@@ -0,0 +1,70 @@
1
+ class FixAdjustmentOrderId < ActiveRecord::Migration
2
+ def change
3
+ say 'Populate order_id from adjustable_id where appropriate'
4
+ execute(<<-SQL.squish)
5
+ UPDATE
6
+ spree_adjustments
7
+ SET
8
+ order_id = adjustable_id
9
+ WHERE
10
+ adjustable_type = 'Spree::Order'
11
+ ;
12
+ SQL
13
+
14
+ # Submitter of change does not care about MySQL, as it is not officially supported.
15
+ # Still spree officials decided to provide a working code path for MySQL users, hence
16
+ # submitter made a AR code path he could validate on PostgreSQL.
17
+ #
18
+ # Whoever runs a big enough MySQL installation where the AR solution hurts:
19
+ # Will have to write a better MySQL specific equivalent.
20
+ if Spree::Order.connection.adapter_name.eql?('MySQL')
21
+ Spree::Adjustment.where(adjustable_type: 'Spree::LineItem').find_each do |adjustment|
22
+ adjustment.update_columns(order_id: Spree::LineItem.find(adjustment.adjustable_id).order_id)
23
+ end
24
+ else
25
+ execute(<<-SQL.squish)
26
+ UPDATE
27
+ spree_adjustments
28
+ SET
29
+ order_id =
30
+ (SELECT order_id FROM spree_line_items WHERE spree_line_items.id = spree_adjustments.adjustable_id)
31
+ WHERE
32
+ adjustable_type = 'Spree::LineItem'
33
+ SQL
34
+ end
35
+
36
+ say 'Fix schema for spree_adjustments order_id column'
37
+ change_table :spree_adjustments do |t|
38
+ t.change :order_id, :integer, null: false
39
+ end
40
+
41
+ # Improved schema for postgresql, uncomment if you like it:
42
+ #
43
+ # # Negated Logical implication.
44
+ # #
45
+ # # When adjustable_type is 'Spree::Order' (p) the adjustable_id must be order_id (q).
46
+ # #
47
+ # # When adjustable_type is NOT 'Spree::Order' the adjustable id allowed to be any value (including of order_id in
48
+ # # case foreign keys match). XOR does not work here.
49
+ # #
50
+ # # Postgresql does not have an operator for logical implication. So we need to build the following truth table
51
+ # # via AND with OR:
52
+ # #
53
+ # # p q | CHECK = !(p -> q)
54
+ # # -----------
55
+ # # t t | t
56
+ # # t f | f
57
+ # # f t | t
58
+ # # f f | t
59
+ # #
60
+ # # According to de-morgans law the logical implication q -> p is equivalent to !p || q
61
+ # #
62
+ # execute(<<-SQL.squish)
63
+ # ALTER TABLE ONLY spree_adjustments
64
+ # ADD CONSTRAINT fk_spree_adjustments FOREIGN KEY (order_id)
65
+ # REFERENCES spree_orders(id) ON UPDATE RESTRICT ON DELETE RESTRICT,
66
+ # ADD CONSTRAINT check_spree_adjustments_order_id CHECK
67
+ # (adjustable_type <> 'Spree::Order' OR order_id = adjustable_id);
68
+ # SQL
69
+ end
70
+ end
@@ -0,0 +1,6 @@
1
+ class AddDeletedAtToFriendlyIdSlugs < ActiveRecord::Migration
2
+ def change
3
+ add_column :friendly_id_slugs, :deleted_at, :datetime
4
+ add_index :friendly_id_slugs, :deleted_at
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ class EnableActsAsParanoidOnCalculators < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_calculators, :deleted_at, :datetime
4
+ add_index :spree_calculators, :deleted_at
5
+ end
6
+ end
@@ -101,6 +101,13 @@ module Spree
101
101
  initializer "spree.core.checking_migrations" do |app|
102
102
  Migrations.new(config, engine_name).check
103
103
  end
104
+
105
+ config.to_prepare do
106
+ # Load application's model / class decorators
107
+ Dir.glob(File.join(File.dirname(__FILE__), '../../../app/**/*_decorator*.rb')) do |c|
108
+ Rails.configuration.cache_classes ? require(c) : load(c)
109
+ end
110
+ end
104
111
  end
105
112
  end
106
113
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
2
  def self.version
3
- "2.4.7"
3
+ "2.4.8"
4
4
  end
5
5
  end
@@ -17,6 +17,17 @@ FactoryGirl.define do
17
17
  end
18
18
  end
19
19
 
20
+ factory :order_with_line_item_quantity do
21
+ transient do
22
+ line_items_quantity 1
23
+ end
24
+
25
+ after(:create) do |order, evaluator|
26
+ create(:line_item, order: order, price: evaluator.line_items_price, quantity: evaluator.line_items_quantity)
27
+ order.line_items.reload # to ensure order.line_items is accessible after
28
+ end
29
+ end
30
+
20
31
  factory :order_with_line_items do
21
32
  bill_address
22
33
  ship_address
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.7
4
+ version: 2.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Schofield
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-05 00:00:00.000000000 Z
11
+ date: 2015-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemerchant
@@ -232,14 +232,14 @@ dependencies:
232
232
  requirements:
233
233
  - - "~>"
234
234
  - !ruby/object:Gem::Version
235
- version: 2.0.5
235
+ version: 2.1.0
236
236
  type: :runtime
237
237
  prerelease: false
238
238
  version_requirements: !ruby/object:Gem::Requirement
239
239
  requirements:
240
240
  - - "~>"
241
241
  - !ruby/object:Gem::Version
242
- version: 2.0.5
242
+ version: 2.1.0
243
243
  - !ruby/object:Gem::Dependency
244
244
  name: premailer-rails
245
245
  requirement: !ruby/object:Gem::Requirement
@@ -258,16 +258,16 @@ dependencies:
258
258
  name: rails
259
259
  requirement: !ruby/object:Gem::Requirement
260
260
  requirements:
261
- - - '='
261
+ - - "~>"
262
262
  - !ruby/object:Gem::Version
263
- version: 4.1.9
263
+ version: 4.1.11
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.9
270
+ version: 4.1.11
271
271
  - !ruby/object:Gem::Dependency
272
272
  name: ransack
273
273
  requirement: !ruby/object:Gem::Requirement
@@ -385,6 +385,7 @@ files:
385
385
  - app/models/concerns/spree/user_api_authentication.rb
386
386
  - app/models/concerns/spree/user_payment_source.rb
387
387
  - app/models/concerns/spree/user_reporting.rb
388
+ - app/models/friendly_id/slug_decorator.rb
388
389
  - app/models/spree/ability.rb
389
390
  - app/models/spree/address.rb
390
391
  - app/models/spree/adjustment.rb
@@ -433,6 +434,7 @@ files:
433
434
  - app/models/spree/order/payments.rb
434
435
  - app/models/spree/order_contents.rb
435
436
  - app/models/spree/order_inventory.rb
437
+ - app/models/spree/order_merger.rb
436
438
  - app/models/spree/order_populator.rb
437
439
  - app/models/spree/order_updater.rb
438
440
  - app/models/spree/payment.rb
@@ -752,6 +754,9 @@ files:
752
754
  - db/migrate/20141101231208_fix_adjustment_order_presence.rb
753
755
  - db/migrate/20141105213646_update_classifications_positions.rb
754
756
  - db/migrate/20141120135441_add_guest_token_index_to_spree_orders.rb
757
+ - db/migrate/20150515211137_fix_adjustment_order_id.rb
758
+ - db/migrate/20150522181728_add_deleted_at_to_friendly_id_slugs.rb
759
+ - db/migrate/20150707204155_enable_acts_as_paranoid_on_calculators.rb
755
760
  - db/seeds.rb
756
761
  - lib/generators/spree/custom_user/custom_user_generator.rb
757
762
  - lib/generators/spree/custom_user/templates/authentication_helpers.rb.tt