solidus_core 1.4.0.beta1 → 1.4.0.rc1

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.

Potentially problematic release.


This version of solidus_core might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8aa4c3e58ebb0c1418f96f55061e429329292ed3
4
- data.tar.gz: 90e3439877e5e1632c288d009a442a05bce4631d
3
+ metadata.gz: c5889aa9a1d498a6573bfefa369fb4530f98b69c
4
+ data.tar.gz: e3e60915860a0ae80dc0e2a1c728ca5754d1017c
5
5
  SHA512:
6
- metadata.gz: cc8e9cba50b0b5eb46b7305513e28e395194d01f4b8304d1929eff3bf2db019d8f6b683691df073890aaf955946a3fdd7bf57d5e935c91c403f2dd68d9dd4488
7
- data.tar.gz: 4b98fa39ceb46b0ccf5c85163bf1fc778f6641eafe8d2e99dd8a249b0657d5232ff74fc025593e3cb14c1ff40b430dc666896d666fd60e7733d404444eac2d05
6
+ metadata.gz: 920ce1f524585315b5133505ab449cb7cbfb74d1d100adfc222238cbde476c7b1da389e0683c359e8679b7409bd50bd46490f4f06175f9dc29471e7b0f899cea
7
+ data.tar.gz: 48cbf7e4f562469a4ee959bf83afd94dcbc2ea09b784677dea321bf0ef8b996d21b83a4214987518ba87c7f94035667a8d8ed08c544ad775232148a9ddc84222
@@ -26,6 +26,11 @@ module Spree
26
26
  validates :amount, numericality: true
27
27
  validates :promotion_code, presence: true, if: :require_promotion_code?
28
28
 
29
+ # We need to use `after_commit` here because otherwise it's too early to
30
+ # tell if any repair is needed.
31
+ after_commit :repair_adjustments_associations_on_create, on: [:create]
32
+ after_commit :repair_adjustments_associations_on_destroy, on: [:destroy]
33
+
29
34
  scope :not_finalized, -> { where(finalized: false) }
30
35
  scope :open, -> do
31
36
  Spree::Deprecation.warn "Adjustment.open is deprecated. Instead use Adjustment.not_finalized", caller
@@ -177,5 +182,19 @@ module Spree
177
182
  def require_promotion_code?
178
183
  promotion? && source.promotion.codes.any?
179
184
  end
185
+
186
+ def repair_adjustments_associations_on_create
187
+ if adjustable.adjustments.loaded? && !adjustable.adjustments.include?(self)
188
+ Spree::Deprecation.warn("Adjustment was not added to #{adjustable.class}. Add adjustments via `adjustable.adjustments.create!`. Partial call stack: #{caller.select { |line| line =~ %r(/(app|spec)/) }}.", caller)
189
+ adjustable.adjustments.proxy_association.add_to_target(self)
190
+ end
191
+ end
192
+
193
+ def repair_adjustments_associations_on_destroy
194
+ if adjustable.adjustments.loaded? && adjustable.adjustments.include?(self)
195
+ Spree::Deprecation.warn("Adjustment was not removed from #{adjustable.class}. Remove adjustments via `adjustable.adjustments.destroy`. Partial call stack: #{caller.select { |line| line =~ %r(/(app|spec)/) }}.", caller)
196
+ adjustable.adjustments.proxy_association.target.delete(self)
197
+ end
198
+ end
180
199
  end
181
200
  end
@@ -83,11 +83,7 @@ module Spree
83
83
  private
84
84
 
85
85
  def adjustments
86
- # This is done intentionally to avoid loading the association. If the
87
- # association is loaded, the records may become stale due to code
88
- # elsewhere in spree. When that is remedied, this should be changed to
89
- # just item.adjustments
90
- @adjustments ||= item.adjustments.all.to_a
86
+ @adjustments ||= item.adjustments.to_a
91
87
  end
92
88
  end
93
89
  end
@@ -47,7 +47,7 @@ module Spree
47
47
  belongs_to :store, class_name: 'Spree::Store'
48
48
  has_many :state_changes, as: :stateful
49
49
  has_many :line_items, -> { order(:created_at, :id) }, dependent: :destroy, inverse_of: :order
50
- has_many :payments, dependent: :destroy
50
+ has_many :payments, dependent: :destroy, inverse_of: :order
51
51
  has_many :return_authorizations, dependent: :destroy, inverse_of: :order
52
52
  has_many :reimbursements, inverse_of: :order
53
53
  has_many :adjustments, -> { order(:created_at) }, as: :adjustable, inverse_of: :adjustable, dependent: :destroy
@@ -503,7 +503,6 @@ module Spree
503
503
  elsif shipments.any? { |s| !s.pending? }
504
504
  raise CannotRebuildShipments.new(Spree.t(:cannot_rebuild_shipments_shipments_not_pending))
505
505
  else
506
- adjustments.shipping.destroy_all
507
506
  shipments.destroy_all
508
507
  self.shipments = Spree::Config.stock.coordinator_class.new(self).shipments
509
508
  end
@@ -511,9 +510,7 @@ module Spree
511
510
 
512
511
  def apply_free_shipping_promotions
513
512
  Spree::PromotionHandler::FreeShipping.new(self).activate
514
- shipments.each { |shipment| ItemAdjustments.new(shipment).update }
515
- updater.update_shipment_total
516
- persist_totals
513
+ update!
517
514
  end
518
515
 
519
516
  # Clean shipments and make order back to address state
@@ -43,10 +43,6 @@ module Spree
43
43
  break if payment_total >= total
44
44
 
45
45
  payment.public_send(method)
46
-
47
- if payment.completed?
48
- self.payment_total += payment.amount
49
- end
50
46
  end
51
47
  rescue Core::GatewayError => e
52
48
  result = !!Spree::Config[:allow_checkout_on_gateway_error]
@@ -21,22 +21,15 @@ class Spree::OrderCapturing
21
21
  Spree::OrderMutex.with_lock!(@order) do
22
22
  uncaptured_amount = @order.display_total.cents
23
23
 
24
- begin
25
- sorted_payments(@order).each do |payment|
26
- amount = [uncaptured_amount, payment.money.cents].min
27
-
28
- if amount > 0
29
- payment.capture!(amount)
30
- uncaptured_amount -= amount
31
- elsif Spree::OrderCapturing.void_unused_payments
32
- payment.void_transaction!
33
- end
24
+ sorted_payments(@order).each do |payment|
25
+ amount = [uncaptured_amount, payment.money.cents].min
26
+
27
+ if amount > 0
28
+ payment.capture!(amount)
29
+ uncaptured_amount -= amount
30
+ elsif Spree::OrderCapturing.void_unused_payments
31
+ payment.void_transaction!
34
32
  end
35
- ensure
36
- # FIXME: Adding the inverse_of on the payments relation for orders -should- fix this,
37
- # however it only appears to make it worse (calling with changes three times instead of once.
38
- # Warrants an investigation. Reloading for now.
39
- @order.reload.update!
40
33
  end
41
34
  end
42
35
  end
@@ -119,7 +119,6 @@ module Spree
119
119
  shipment = options[:shipment]
120
120
  shipment.present? ? shipment.update_amounts : order.ensure_updated_shipments
121
121
  PromotionHandler::Cart.new(order, line_item).activate
122
- ItemAdjustments.new(line_item).update
123
122
  reload_totals
124
123
  line_item
125
124
  end
@@ -80,11 +80,11 @@ module Spree
80
80
 
81
81
  all_items = line_items + shipments
82
82
 
83
- order.adjustment_total = all_items.sum(&:adjustment_total) + adjustments.eligible.sum(:amount)
83
+ order.adjustment_total = all_items.sum(&:adjustment_total) + adjustments.select(&:eligible?).sum(&:amount)
84
84
  order.included_tax_total = all_items.sum(&:included_tax_total)
85
85
  order.additional_tax_total = all_items.sum(&:additional_tax_total)
86
86
 
87
- order.promo_total = all_items.sum(&:promo_total) + adjustments.promotion.eligible.sum(:amount)
87
+ order.promo_total = all_items.sum(&:promo_total) + adjustments.select(&:eligible?).select(&:promotion?).sum(&:amount)
88
88
 
89
89
  update_order_total
90
90
  end
@@ -22,10 +22,9 @@ module Spree
22
22
  return if promotion_credit_exists?(order)
23
23
 
24
24
  amount = compute_amount(order)
25
- Spree::Adjustment.create!(
25
+ order.adjustments.create!(
26
26
  amount: amount,
27
27
  order: order,
28
- adjustable: order,
29
28
  source: self,
30
29
  promotion_code: options[:promotion_code],
31
30
  label: "#{Spree.t(:promotion)} (#{promotion.name})"
@@ -40,9 +40,9 @@ module Spree
40
40
  def create_adjustment(adjustable, order, promotion_code)
41
41
  amount = compute_amount(adjustable)
42
42
  return if amount == 0
43
- adjustments.create!(
43
+ adjustable.adjustments.create!(
44
+ source: self,
44
45
  amount: amount,
45
- adjustable: adjustable,
46
46
  order: order,
47
47
  promotion_code: promotion_code,
48
48
  label: "#{Spree.t(:promotion)} (#{promotion.name})"
@@ -15,7 +15,6 @@ module Spree
15
15
  @rates_for_order_zone = options[:rates_for_order_zone]
16
16
  @rates_for_default_zone = options[:rates_for_default_zone]
17
17
  @order_tax_zone = options[:order_tax_zone]
18
- @skip_destroy_adjustments = options[:skip_destroy_adjustments]
19
18
  end
20
19
 
21
20
  # Deletes all existing tax adjustments and creates new adjustments for all
@@ -27,8 +26,8 @@ module Spree
27
26
  # @return [Array<Spree::Adjustment>] newly created adjustments
28
27
  def adjust!
29
28
  return unless order_tax_zone(order)
30
- # Using .destroy_all to make sure callbacks fire
31
- item.adjustments.tax.destroy_all unless @skip_destroy_adjustments
29
+
30
+ item.adjustments.destroy(item.adjustments.select(&:tax?))
32
31
 
33
32
  rates_for_item(item).map { |rate| rate.adjust(order_tax_zone(order), item) }
34
33
  end
@@ -16,8 +16,6 @@ module Spree
16
16
  def adjust!
17
17
  return unless order_tax_zone(order)
18
18
 
19
- order.all_adjustments.tax.destroy_all
20
-
21
19
  (order.line_items + order.shipments).each do |item|
22
20
  ItemAdjuster.new(item, order_wide_options).adjust!
23
21
  end
@@ -30,7 +28,6 @@ module Spree
30
28
  rates_for_order_zone: rates_for_order_zone(order),
31
29
  rates_for_default_zone: rates_for_default_zone,
32
30
  order_tax_zone: order_tax_zone(order),
33
- skip_destroy_adjustments: true
34
31
  }
35
32
  end
36
33
  end
@@ -85,13 +85,13 @@ module Spree
85
85
 
86
86
  included = included_in_price && amount > 0
87
87
 
88
- adjustments.create!({
89
- adjustable: item,
88
+ item.adjustments.create!(
89
+ source: self,
90
90
  amount: amount,
91
91
  order_id: item.order_id,
92
92
  label: adjustment_label(amount),
93
93
  included: included
94
- })
94
+ )
95
95
  end
96
96
 
97
97
  # This method is used by Adjustment#update to recalculate the cost.
@@ -16,8 +16,8 @@ class Spree::UnitCancel < Spree::Base
16
16
 
17
17
  amount = compute_amount(inventory_unit.line_item)
18
18
 
19
- create_adjustment!(
20
- adjustable: inventory_unit.line_item,
19
+ self.adjustment = inventory_unit.line_item.adjustments.create!(
20
+ source: self,
21
21
  amount: amount,
22
22
  order: inventory_unit.order,
23
23
  label: "#{Spree.t(:cancellation)} - #{reason}",
@@ -5,7 +5,7 @@ module Spree
5
5
  end
6
6
 
7
7
  def self.solidus_version
8
- "1.4.0.beta1"
8
+ "1.4.0.rc1"
9
9
  end
10
10
 
11
11
  def self.solidus_gem_version
@@ -12,22 +12,27 @@ FactoryGirl.define do
12
12
  label 'Shipping'
13
13
  association(:source, factory: :tax_rate)
14
14
  eligible true
15
- end
16
15
 
17
- factory :tax_adjustment, class: Spree::Adjustment do
18
- order { adjustable.order }
19
- association(:adjustable, factory: :line_item)
20
- amount 10.0
21
- label 'VAT 5%'
22
- association(:source, factory: :tax_rate)
23
- eligible true
16
+ after(:build) do |adjustment|
17
+ adjustments = adjustment.adjustable.adjustments
18
+ if adjustments.loaded? && !adjustments.include?(adjustment)
19
+ adjustments.proxy_association.add_to_target(adjustment)
20
+ end
21
+ end
22
+
23
+ factory :tax_adjustment, class: Spree::Adjustment do
24
+ order { adjustable.order }
25
+ association(:adjustable, factory: :line_item)
26
+ amount 10.0
27
+ label 'VAT 5%'
24
28
 
25
- after(:create) do |adjustment|
26
- # Set correct tax category, so that adjustment amount is not 0
27
- if adjustment.adjustable.is_a?(Spree::LineItem)
28
- adjustment.source.tax_category = adjustment.adjustable.tax_category
29
- adjustment.source.save
30
- adjustment.update!
29
+ after(:create) do |adjustment|
30
+ # Set correct tax category, so that adjustment amount is not 0
31
+ if adjustment.adjustable.is_a?(Spree::LineItem)
32
+ adjustment.source.tax_category = adjustment.adjustable.tax_category
33
+ adjustment.source.save
34
+ adjustment.update!
35
+ end
31
36
  end
32
37
  end
33
38
  end
@@ -18,7 +18,7 @@ describe "order_capturing:capture_payments" do
18
18
 
19
19
  context "with a mix of canceled and shipped inventory" do
20
20
  before do
21
- Spree::OrderCancellations.new(order).short_ship([order.inventory_units.first])
21
+ Spree::OrderCancellations.new(order).short_ship([order.line_items.first.inventory_units.first])
22
22
  order.shipping.ship_shipment(order.shipments.first)
23
23
  order.update_attributes!(payment_state: 'balance_due')
24
24
  end
@@ -272,6 +272,9 @@ module Spree
272
272
  context "multiple updates" do
273
273
  let(:adjustment) { create(:tax_adjustment, amount: -10) }
274
274
  let(:item) { adjustment.adjustable }
275
+ # we need to get this from the line item so that we're modifying the same
276
+ # tax rate that is cached by line_item.adjustments
277
+ let(:source) { item.adjustments.to_a.first.source }
275
278
 
276
279
  def update
277
280
  described_class.new(item).update
@@ -283,18 +286,17 @@ module Spree
283
286
  end
284
287
 
285
288
  it "persists each change" do
286
- adjustment.source.update_attributes!(amount: 0.1)
289
+ source.update_attributes!(amount: 0.1)
287
290
  update
288
291
  expect(item).not_to be_changed
289
292
  expect(db_record).to have_attributes(adjustment_total: 1)
290
293
 
291
- adjustment.source.update_attributes!(amount: 0.20)
292
- item.reload
294
+ source.update_attributes!(amount: 0.20)
293
295
  update
294
296
  expect(item).not_to be_changed
295
297
  expect(db_record).to have_attributes(adjustment_total: 2)
296
298
 
297
- adjustment.source.update_attributes!(amount: 0.10)
299
+ source.update_attributes!(amount: 0.10)
298
300
  update
299
301
  expect(item).not_to be_changed
300
302
  expect(db_record).to have_attributes(adjustment_total: 1)
@@ -6,49 +6,53 @@ module Spree
6
6
  let(:updater) { Spree::OrderUpdater.new(order) }
7
7
 
8
8
  context "processing payments" do
9
+ let(:order) { create(:order_with_line_items, shipment_cost: 0, line_items_price: 100) }
9
10
  before do
10
11
  # So that Payment#purchase! is called during processing
11
12
  Spree::Config[:auto_capture] = true
12
-
13
- allow(order).to receive_message_chain(:line_items, :empty?).and_return(false)
14
- allow(order).to receive_messages total: 100
15
13
  end
16
14
 
17
15
  it 'processes all checkout payments' do
18
- payment_1 = create(:payment, amount: 50)
19
- payment_2 = create(:payment, amount: 50)
20
- allow(order).to receive(:unprocessed_payments).and_return([payment_1, payment_2])
16
+ payment_1 = create(:payment, order: order, amount: 50)
17
+ payment_2 = create(:payment, order: order, amount: 50)
21
18
 
22
19
  order.process_payments!
23
20
  updater.update_payment_state
21
+
24
22
  expect(order.payment_state).to eq('paid')
23
+ expect(order.payment_total).to eq(100)
25
24
 
26
- expect(payment_1).to be_completed
27
- expect(payment_2).to be_completed
25
+ expect(payment_1.reload).to be_completed
26
+ expect(payment_2.reload).to be_completed
28
27
  end
29
28
 
30
29
  it 'does not go over total for order' do
31
- payment_1 = create(:payment, amount: 50)
32
- payment_2 = create(:payment, amount: 50)
33
- payment_3 = create(:payment, amount: 50)
34
- allow(order).to receive(:unprocessed_payments).and_return([payment_1, payment_2, payment_3])
30
+ payment_1 = create(:payment, order: order, amount: 50)
31
+ payment_2 = create(:payment, order: order, amount: 50)
32
+ payment_3 = create(:payment, order: order, amount: 50)
35
33
 
36
34
  order.process_payments!
37
35
  updater.update_payment_state
36
+
38
37
  expect(order.payment_state).to eq('paid')
38
+ expect(order.payment_total).to eq(100)
39
39
 
40
- expect(payment_1).to be_completed
41
- expect(payment_2).to be_completed
42
- expect(payment_3).to be_checkout
40
+ expect(payment_1.reload).to be_completed
41
+ expect(payment_2.reload).to be_completed
42
+ expect(payment_3.reload).to be_checkout
43
43
  end
44
44
 
45
45
  it "does not use failed payments" do
46
- payment_1 = create(:payment, amount: 50)
47
- payment_2 = create(:payment, amount: 50, state: 'failed')
46
+ create(:payment, order: order, amount: 50)
47
+ create(:payment, order: order, amount: 50, state: 'failed')
48
+ order.payments.reload
48
49
 
49
- expect(payment_2).not_to receive(:process!)
50
+ expect(order.payments[0]).to receive(:process!).and_call_original
51
+ expect(order.payments[1]).not_to receive(:process!)
50
52
 
51
53
  order.process_payments!
54
+
55
+ expect(order.payment_total).to eq(50)
52
56
  end
53
57
  end
54
58
 
@@ -139,9 +139,9 @@ describe Spree::OrderCancellations do
139
139
  order.contents.add(line_item.variant)
140
140
 
141
141
  # make the total $1.67 so it divides unevenly
142
- Spree::Adjustment.tax.create!(
142
+ line_item.adjustments.create!(
143
+ source_type: 'Spree::TaxRate',
143
144
  order: order,
144
- adjustable: line_item,
145
145
  amount: 0.01,
146
146
  label: 'some fake tax',
147
147
  finalized: true
@@ -4,8 +4,8 @@ describe Spree::OrderCapturing do
4
4
  describe '#capture_payments' do
5
5
  subject { Spree::OrderCapturing.new(order, payment_methods).capture_payments }
6
6
 
7
- # Regression for the order.update! in the ensure block.
8
- # See the comment there.
7
+ # Regression for https://github.com/solidusio/solidus/pull/407
8
+ # See also https://github.com/solidusio/solidus/pull/1406
9
9
  context "updating the order" do
10
10
  let(:order) { create :completed_order_with_totals }
11
11
  let(:payment_methods) { [] }
@@ -591,16 +591,12 @@ describe Spree::Order, type: :model do
591
591
 
592
592
  context "#apply_free_shipping_promotions" do
593
593
  it "calls out to the FreeShipping promotion handler" do
594
- shipment = double('Shipment')
595
- allow(order).to receive_messages shipments: [shipment]
596
- expect(Spree::PromotionHandler::FreeShipping).to receive(:new).and_return(handler = double)
597
- expect(handler).to receive(:activate)
594
+ expect_any_instance_of(Spree::PromotionHandler::FreeShipping).to(
595
+ receive(:activate)
596
+ ).and_call_original
598
597
 
599
- expect(Spree::ItemAdjustments).to receive(:new).with(shipment).and_return(adjuster = double)
600
- expect(adjuster).to receive(:update)
598
+ expect(order.updater).to receive(:update).and_call_original
601
599
 
602
- expect(order.updater).to receive(:update_shipment_total)
603
- expect(order.updater).to receive(:persist_totals)
604
600
  order.apply_free_shipping_promotions
605
601
  end
606
602
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe Spree::Tax::ItemAdjuster do
4
4
  subject(:adjuster) { described_class.new(item) }
5
- let(:order) { Spree::Order.new }
5
+ let(:order) { create(:order) }
6
6
  let(:item) { Spree::LineItem.new(order: order) }
7
7
 
8
8
  before do
@@ -64,7 +64,6 @@ RSpec.describe Spree::Tax::ItemAdjuster do
64
64
  before { allow(item).to receive(:tax_category).and_return(item_tax_category) }
65
65
 
66
66
  it 'creates an adjustment for every matching rate' do
67
- expect(rate_1).to receive_message_chain(:adjustments, :create!)
68
67
  expect(adjuster.adjust!.length).to eq(1)
69
68
  end
70
69
  end
@@ -31,7 +31,6 @@ RSpec.describe Spree::Tax::OrderAdjuster do
31
31
  rates_for_order_zone: rates_for_order_zone,
32
32
  rates_for_default_zone: [],
33
33
  order_tax_zone: zone,
34
- skip_destroy_adjustments: true
35
34
  ).and_return(item_adjuster)
36
35
  expect(Spree::Tax::ItemAdjuster).to receive(:new).
37
36
  with(
@@ -39,7 +38,6 @@ RSpec.describe Spree::Tax::OrderAdjuster do
39
38
  rates_for_order_zone: rates_for_order_zone,
40
39
  rates_for_default_zone: [],
41
40
  order_tax_zone: zone,
42
- skip_destroy_adjustments: true
43
41
  ).and_return(item_adjuster)
44
42
 
45
43
  expect(item_adjuster).to receive(:adjust!).twice
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidus_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0.beta1
4
+ version: 1.4.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Solidus Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-19 00:00:00.000000000 Z
11
+ date: 2016-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemerchant