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 +4 -4
- data/app/models/friendly_id/slug_decorator.rb +3 -0
- data/app/models/spree/adjustment.rb +1 -1
- data/app/models/spree/calculator.rb +5 -0
- data/app/models/spree/customer_return.rb +22 -16
- data/app/models/spree/gateway/bogus.rb +4 -0
- data/app/models/spree/order.rb +14 -41
- data/app/models/spree/order_contents.rb +7 -8
- data/app/models/spree/order_merger.rb +65 -0
- data/app/models/spree/order_updater.rb +0 -5
- data/app/models/spree/payment.rb +5 -0
- data/app/models/spree/payment/processing.rb +2 -1
- data/app/models/spree/product.rb +7 -1
- data/app/models/spree/promotion_handler/cart.rb +18 -14
- data/app/models/spree/promotion_handler/coupon.rb +1 -1
- data/app/models/spree/shipment.rb +1 -1
- data/app/models/spree/stock/availability_validator.rb +10 -6
- data/app/models/spree/stock_item.rb +5 -1
- data/app/models/spree/stock_movement.rb +6 -1
- data/app/models/spree/tax_rate.rb +5 -1
- data/app/models/spree/variant.rb +1 -6
- data/config/initializers/user_class_extensions.rb +4 -0
- data/config/locales/en.yml +1 -1
- data/db/migrate/20150515211137_fix_adjustment_order_id.rb +70 -0
- data/db/migrate/20150522181728_add_deleted_at_to_friendly_id_slugs.rb +6 -0
- data/db/migrate/20150707204155_enable_acts_as_paranoid_on_calculators.rb +6 -0
- data/lib/spree/core/engine.rb +7 -0
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/testing_support/factories/order_factory.rb +11 -0
- metadata +13 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a4b6e2afb0968da8792da3d641cde6a8628eb48
|
4
|
+
data.tar.gz: c2c33ca5c66f6f1c4f2165b4e388f14d82884e91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d115ad863b2eecbf62c10eca8635ad099eef6ed3228da587d6b17238e5f1da29664d7eea5ecca3fc579f599c697147d1d097f657bd1e9a0e7e02e44d80944931
|
7
|
+
data.tar.gz: 3999bfb8c5830d8ecdfccc20fa5921a4e358ee925348f71611c66272683526cdbe57ab9207c327471f50bb40e839d12f143859d1c9bda97bd6c17caaa7a87de1
|
@@ -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:
|
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
|
19
|
-
return_items.
|
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
|
37
|
-
|
42
|
+
def pre_tax_total
|
43
|
+
return_items.sum(:pre_tax_amount)
|
38
44
|
end
|
39
45
|
|
40
|
-
|
41
|
-
|
46
|
+
private
|
47
|
+
|
48
|
+
def inventory_units
|
49
|
+
return_items.flat_map(&:inventory_unit)
|
42
50
|
end
|
43
51
|
|
44
|
-
|
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
|
data/app/models/spree/order.rb
CHANGED
@@ -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
|
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.
|
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
|
-
|
25
|
+
persist_totals
|
26
26
|
PromotionHandler::Cart.new(order).activate
|
27
27
|
order.ensure_updated_shipments
|
28
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
94
|
-
|
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
|
data/app/models/spree/payment.rb
CHANGED
@@ -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
|
data/app/models/spree/product.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
|
@@ -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
|
-
|
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
|
-
|
17
|
-
|
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
|
-
|
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
|
-
|
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)
|
data/app/models/spree/variant.rb
CHANGED
@@ -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
|
data/config/locales/en.yml
CHANGED
@@ -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
|
data/lib/spree/core/engine.rb
CHANGED
@@ -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
|
data/lib/spree/core/version.rb
CHANGED
@@ -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.
|
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-
|
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
|
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
|
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.
|
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.
|
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
|