spree_core 2.4.7 → 2.4.8

Sign up to get free protection for your applications and to get access to all the features.
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