solidus_core 2.0.3 → 2.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of solidus_core might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +62 -3
- data/app/assets/javascripts/spree.js.coffee.erb +4 -1
- data/app/helpers/spree/base_helper.rb +7 -48
- data/app/models/spree/address.rb +5 -1
- data/app/models/spree/adjustment.rb +3 -3
- data/app/models/spree/app_configuration.rb +13 -0
- data/app/models/spree/calculator.rb +3 -2
- data/app/models/spree/calculator/default_tax.rb +6 -10
- data/app/models/spree/calculator/flat_percent_item_total.rb +0 -4
- data/app/models/spree/calculator/flat_rate.rb +0 -4
- data/app/models/spree/calculator/flexi_rate.rb +0 -4
- data/app/models/spree/calculator/free_shipping.rb +0 -3
- data/app/models/spree/calculator/percent_on_line_item.rb +0 -4
- data/app/models/spree/calculator/percent_per_item.rb +0 -4
- data/app/models/spree/calculator/price_sack.rb +0 -4
- data/app/models/spree/calculator/returns/default_refund_amount.rb +0 -3
- data/app/models/spree/calculator/shipping/flat_percent_item_total.rb +0 -4
- data/app/models/spree/calculator/shipping/flat_rate.rb +0 -4
- data/app/models/spree/calculator/shipping/flexi_rate.rb +0 -4
- data/app/models/spree/calculator/shipping/per_item.rb +0 -4
- data/app/models/spree/calculator/shipping/price_sack.rb +0 -4
- data/app/models/spree/calculator/tiered_flat_rate.rb +0 -4
- data/app/models/spree/calculator/tiered_percent.rb +0 -4
- data/app/models/spree/credit_card.rb +27 -14
- data/app/models/spree/gateway.rb +4 -0
- data/app/models/spree/inventory_unit.rb +2 -0
- data/app/models/spree/line_item.rb +31 -26
- data/app/models/spree/option_type.rb +0 -3
- data/app/models/spree/order.rb +28 -31
- data/app/models/spree/order/checkout.rb +0 -2
- data/app/models/spree/order_contents.rb +0 -45
- data/app/models/spree/order_merger.rb +6 -6
- data/app/models/spree/order_update_attributes.rb +0 -2
- data/app/models/spree/order_updater.rb +91 -13
- data/app/models/spree/payment.rb +9 -2
- data/app/models/spree/payment/processing.rb +15 -9
- data/app/models/spree/payment_method.rb +48 -5
- data/app/models/spree/price.rb +7 -9
- data/app/models/spree/product.rb +1 -25
- data/app/models/spree/promotion.rb +22 -14
- data/app/models/spree/promotion/actions/create_adjustment.rb +12 -1
- data/app/models/spree/promotion/actions/create_item_adjustments.rb +15 -1
- data/app/models/spree/promotion/actions/create_quantity_adjustments.rb +5 -3
- data/app/models/spree/promotion/actions/free_shipping.rb +14 -0
- data/app/models/spree/promotion/rules/taxon.rb +7 -2
- data/app/models/spree/promotion/rules/user_role.rb +43 -0
- data/app/models/spree/promotion_action.rb +19 -2
- data/app/models/spree/promotion_handler/coupon.rb +1 -4
- data/app/models/spree/promotion_handler/free_shipping.rb +22 -17
- data/app/models/spree/promotion_rule_role.rb +6 -0
- data/app/models/spree/property.rb +0 -3
- data/app/models/spree/return_authorization.rb +2 -0
- data/app/models/spree/shipment.rb +5 -21
- data/app/models/spree/shipping_method.rb +23 -2
- data/app/models/spree/shipping_rate.rb +3 -0
- data/app/models/spree/stock/estimator.rb +1 -1
- data/app/models/spree/stock_location.rb +3 -0
- data/app/models/spree/store.rb +7 -0
- data/app/models/spree/tax/item_adjuster.rb +27 -12
- data/app/models/spree/tax/order_adjuster.rb +2 -5
- data/app/models/spree/tax/tax_helpers.rb +4 -8
- data/app/models/spree/tax_rate.rb +1 -15
- data/app/models/spree/taxon.rb +0 -3
- data/app/models/spree/transfer_item.rb +1 -1
- data/app/models/spree/user_class_handle.rb +14 -9
- data/app/models/spree/variant/pricing_options.rb +1 -1
- data/app/models/spree/wallet/add_payment_sources_to_wallet.rb +1 -1
- data/app/models/spree/zone.rb +20 -13
- data/config/locales/en.yml +144 -62
- data/db/migrate/20120831092320_spree_one_two.rb +0 -7
- data/db/migrate/20150723224133_remove_unnecessary_indexes.rb +0 -2
- data/db/migrate/20160924135758_remove_is_default_from_prices.rb +5 -0
- data/db/migrate/20161009141333_remove_currency_from_line_items.rb +5 -0
- data/db/migrate/20161014221052_add_available_to_columns_and_remove_display_on_from_payment_methods.rb +28 -0
- data/db/migrate/20161123154034_add_available_to_users_and_remove_display_on_from_shipping_methods.rb +20 -0
- data/lib/generators/spree/custom_user/templates/authentication_helpers.rb.tt +4 -0
- data/lib/generators/spree/dummy/dummy_generator.rb +0 -2
- data/lib/spree/core.rb +0 -5
- data/lib/spree/core/controller_helpers/pricing.rb +2 -1
- data/lib/spree/core/engine.rb +14 -0
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/deprecation.rb +1 -1
- data/lib/spree/localized_number.rb +3 -2
- data/lib/spree/permission_sets/configuration_display.rb +0 -1
- data/lib/spree/permission_sets/configuration_management.rb +0 -1
- data/lib/spree/permission_sets/product_display.rb +0 -1
- data/lib/spree/permission_sets/product_management.rb +0 -1
- data/lib/spree/permission_sets/user_management.rb +2 -4
- data/lib/spree/permitted_attributes.rb +3 -2
- data/lib/spree/testing_support/capybara_ext.rb +0 -12
- data/lib/spree/testing_support/factories/address_factory.rb +1 -1
- data/lib/spree/testing_support/factories/line_item_factory.rb +0 -1
- data/lib/spree/testing_support/factories/payment_factory.rb +4 -0
- data/lib/spree/testing_support/factories/payment_method_factory.rb +8 -1
- data/lib/spree/testing_support/factories/user_factory.rb +2 -2
- data/solidus_core.gemspec +4 -3
- data/spec/helpers/base_helper_spec.rb +0 -40
- data/spec/lib/spree/core/controller_helpers/pricing_spec.rb +16 -0
- data/spec/lib/spree/core/importer/order_spec.rb +27 -18
- data/spec/lib/spree/core/price_migrator_spec.rb +3 -1
- data/spec/lib/spree/core/testing_support/factories/order_factory_spec.rb +16 -0
- data/spec/lib/spree/core/unreturned_item_charger_spec.rb +0 -2
- data/spec/lib/tasks/exchanges_spec.rb +4 -2
- data/spec/lib/tasks/migrations/create_vat_prices_spec.rb +5 -3
- data/spec/models/spree/adjustment_spec.rb +136 -0
- data/spec/models/spree/calculator/default_tax_spec.rb +13 -7
- data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +3 -0
- data/spec/models/spree/calculator/flat_rate_spec.rb +3 -0
- data/spec/models/spree/calculator/flexi_rate_spec.rb +3 -0
- data/spec/models/spree/calculator/free_shipping_spec.rb +6 -0
- data/spec/models/spree/calculator/percent_on_line_item_spec.rb +9 -4
- data/spec/models/spree/calculator/percent_per_item_spec.rb +10 -0
- data/spec/models/spree/calculator/price_sack_spec.rb +3 -0
- data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +3 -0
- data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +3 -0
- data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +3 -0
- data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +3 -0
- data/spec/models/spree/calculator/shipping/per_item_spec.rb +3 -0
- data/spec/models/spree/calculator/shipping/price_sack_spec.rb +4 -1
- data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +3 -0
- data/spec/models/spree/calculator/tiered_percent_spec.rb +3 -0
- data/spec/models/spree/credit_card_spec.rb +27 -1
- data/spec/models/spree/line_item_spec.rb +58 -65
- data/spec/models/spree/order/checkout_spec.rb +2 -1
- data/spec/models/spree/order/payment_spec.rb +9 -10
- data/spec/models/spree/order/tax_spec.rb +22 -7
- data/spec/models/spree/order/updating_spec.rb +1 -3
- data/spec/models/spree/order_cancellations_spec.rb +6 -4
- data/spec/models/spree/order_contents_spec.rb +34 -50
- data/spec/models/spree/order_inventory_spec.rb +3 -5
- data/spec/models/spree/order_merger_spec.rb +20 -0
- data/spec/models/spree/order_spec.rb +28 -64
- data/spec/models/spree/order_update_attributes_spec.rb +1 -5
- data/spec/models/spree/order_updater_spec.rb +251 -0
- data/spec/models/spree/payment_method_spec.rb +178 -28
- data/spec/models/spree/payment_spec.rb +35 -19
- data/spec/models/spree/permission_sets/configuration_display.rb +0 -4
- data/spec/models/spree/permission_sets/configuration_management_spec.rb +0 -2
- data/spec/models/spree/permission_sets/product_display_spec.rb +0 -4
- data/spec/models/spree/permission_sets/product_management_spec.rb +0 -2
- data/spec/models/spree/permission_sets/user_management_spec.rb +9 -2
- data/spec/models/spree/price_spec.rb +16 -1
- data/spec/models/spree/product_spec.rb +0 -75
- data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +20 -0
- data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +39 -15
- data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +203 -22
- data/spec/models/spree/promotion/actions/free_shipping_spec.rb +22 -3
- data/spec/models/spree/promotion/rules/taxon_spec.rb +26 -0
- data/spec/models/spree/promotion/rules/user_role_spec.rb +86 -0
- data/spec/models/spree/promotion_action_spec.rb +38 -0
- data/spec/models/spree/promotion_handler/coupon_spec.rb +36 -33
- data/spec/models/spree/promotion_handler/free_shipping_spec.rb +21 -22
- data/spec/models/spree/promotion_spec.rb +46 -6
- data/spec/models/spree/reimbursement_spec.rb +1 -1
- data/spec/models/spree/reimbursement_tax_calculator_spec.rb +2 -2
- data/spec/models/spree/shipment_spec.rb +68 -50
- data/spec/models/spree/shipping_method_spec.rb +41 -0
- data/spec/models/spree/shipping_rate_spec.rb +9 -3
- data/spec/models/spree/stock/estimator_spec.rb +4 -2
- data/spec/models/spree/store_credit_spec.rb +3 -3
- data/spec/models/spree/tax/item_adjuster_spec.rb +31 -21
- data/spec/models/spree/tax/order_adjuster_spec.rb +6 -10
- data/spec/models/spree/tax/taxation_integration_spec.rb +19 -0
- data/spec/models/spree/tax_rate_spec.rb +5 -26
- data/spec/models/spree/transfer_item_spec.rb +11 -0
- data/spec/models/spree/variant/pricing_options_spec.rb +7 -17
- data/spec/models/spree/variant_spec.rb +2 -4
- data/spec/models/spree/zone_spec.rb +60 -20
- data/spec/shared_examples/calculator_shared_examples.rb +8 -0
- metadata +19 -24
- data/app/models/spree/item_adjustments.rb +0 -89
- data/app/models/spree/option_type_prototype.rb +0 -6
- data/app/models/spree/property_prototype.rb +0 -6
- data/app/models/spree/prototype.rb +0 -14
- data/app/models/spree/prototype_taxon.rb +0 -6
- data/app/models/spree/tracker.rb +0 -8
- data/db/migrate/20150128032538_remove_environment_from_tracker.rb +0 -6
- data/lib/generators/spree/dummy/templates/initializers/custom_user.rb +0 -1
- data/lib/spree/core/delegate_belongs_to.rb +0 -94
- data/lib/spree/testing_support/factories/prototype_factory.rb +0 -8
- data/lib/spree/testing_support/factories/tracker_factory.rb +0 -6
- data/spec/lib/spree/core/delegate_belongs_to_spec.rb +0 -24
- data/spec/lib/spree/core/testing_support/factories/prototype_factory_spec.rb +0 -12
- data/spec/lib/spree/core/testing_support/factories/tracker_factory_spec.rb +0 -12
- data/spec/models/spree/item_adjustments_spec.rb +0 -306
- data/spec/models/spree/tracker_spec.rb +0 -21
@@ -1,11 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Spree::Order, type: :model do
|
4
|
-
let(:order) {
|
4
|
+
let(:order) { create(:order) }
|
5
5
|
|
6
6
|
context "#update!" do
|
7
|
-
let(:line_items) { [mock_model(Spree::LineItem, amount: 5)] }
|
8
|
-
|
9
7
|
context "when there are update hooks" do
|
10
8
|
before { Spree::Order.register_update_hook :foo }
|
11
9
|
after { Spree::Order.update_hooks.clear }
|
@@ -134,17 +134,19 @@ describe Spree::OrderCancellations do
|
|
134
134
|
let(:line_item) { order.line_items.to_a.first }
|
135
135
|
let(:inventory_unit_1) { line_item.inventory_units[0] }
|
136
136
|
let(:inventory_unit_2) { line_item.inventory_units[1] }
|
137
|
+
let(:promotion) { create(:promotion, :with_line_item_adjustment) }
|
138
|
+
let(:promotion_action) { promotion.actions[0] }
|
137
139
|
|
138
140
|
before do
|
139
141
|
order.contents.add(line_item.variant)
|
140
142
|
|
141
143
|
# make the total $1.67 so it divides unevenly
|
142
144
|
line_item.adjustments.create!(
|
143
|
-
source_type: 'Spree::TaxRate',
|
144
145
|
order: order,
|
145
146
|
amount: 0.01,
|
146
|
-
label: 'some
|
147
|
-
|
147
|
+
label: 'some promo',
|
148
|
+
source: promotion_action,
|
149
|
+
finalized: true,
|
148
150
|
)
|
149
151
|
order.update!
|
150
152
|
end
|
@@ -154,7 +156,7 @@ describe Spree::OrderCancellations do
|
|
154
156
|
order.cancellations.short_ship([inventory_unit_2])
|
155
157
|
expect(line_item.adjustments.map(&:amount)).to match_array(
|
156
158
|
[
|
157
|
-
0.01,
|
159
|
+
0.01, # promo adjustment
|
158
160
|
-0.84, # short ship 1
|
159
161
|
-0.83, # short ship 2
|
160
162
|
]
|
@@ -2,12 +2,12 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Spree::OrderContents, type: :model do
|
4
4
|
let!(:store) { create :store }
|
5
|
-
let(:order) {
|
5
|
+
let(:order) { create(:order) }
|
6
6
|
let(:variant) { create(:variant) }
|
7
7
|
let!(:stock_location) { variant.stock_locations.first }
|
8
8
|
let(:stock_location_2) { create(:stock_location) }
|
9
9
|
|
10
|
-
subject { described_class.new(order) }
|
10
|
+
subject(:order_contents) { described_class.new(order) }
|
11
11
|
|
12
12
|
context "#add" do
|
13
13
|
context 'given quantity is not explicitly provided' do
|
@@ -96,6 +96,38 @@ describe Spree::OrderContents, type: :model do
|
|
96
96
|
include_context "discount changes order total"
|
97
97
|
end
|
98
98
|
end
|
99
|
+
|
100
|
+
describe 'tax calculations' do
|
101
|
+
let!(:zone) { create(:global_zone) }
|
102
|
+
let!(:tax_rate) do
|
103
|
+
create(:tax_rate, zone: zone, tax_category: variant.tax_category)
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'when the order has a taxable address' do
|
107
|
+
before do
|
108
|
+
expect(order.tax_address.country_id).to be_present
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'creates a tax adjustment' do
|
112
|
+
order_contents.add(variant)
|
113
|
+
line_item = order.find_line_item_by_variant(variant)
|
114
|
+
expect(line_item.adjustments.tax.count).to eq(1)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'when the order does not have a taxable address' do
|
119
|
+
before do
|
120
|
+
order.update_attributes!(ship_address: nil, bill_address: nil)
|
121
|
+
expect(order.tax_address.country_id).to be_nil
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'creates a tax adjustment' do
|
125
|
+
order_contents.add(variant)
|
126
|
+
line_item = order.find_line_item_by_variant(variant)
|
127
|
+
expect(line_item.adjustments.tax.count).to eq(0)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
99
131
|
end
|
100
132
|
|
101
133
|
context "#remove" do
|
@@ -224,54 +256,6 @@ describe Spree::OrderContents, type: :model do
|
|
224
256
|
}.to change { subject.order.total }
|
225
257
|
end
|
226
258
|
|
227
|
-
context "given an order with existing addresses" do
|
228
|
-
let(:default_address) { create :address, state_code: "NY", zipcode: "17402" }
|
229
|
-
let(:order_with_address ) { create :order, ship_address: default_address, bill_address: default_address }
|
230
|
-
|
231
|
-
subject { described_class.new(order_with_address) }
|
232
|
-
|
233
|
-
context "when an address in a potentially different tax zone is supplied " do
|
234
|
-
let(:updated_address) { build :address, state_code: "AL", zipcode: "64092" }
|
235
|
-
|
236
|
-
let(:params) do
|
237
|
-
{ ship_address_attributes: updated_address.value_attributes, bill_address_attributes: updated_address.value_attributes }
|
238
|
-
end
|
239
|
-
|
240
|
-
it "updates tax adjustments" do
|
241
|
-
expect(subject.order).to receive(:create_tax_charge!)
|
242
|
-
subject.update_cart params
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
context "when an address in potentially the same tax zone is supplied" do
|
247
|
-
let(:updated_address) { build :address, state_code: "NY", zipcode: "17402", firstname: 'Robert' }
|
248
|
-
|
249
|
-
let(:params) do
|
250
|
-
{ ship_address_attributes: updated_address.value_attributes, bill_address_attributes: updated_address.value_attributes }
|
251
|
-
end
|
252
|
-
|
253
|
-
it "does not updates tax adjustments" do
|
254
|
-
expect(subject.order).not_to receive(:create_tax_charge!)
|
255
|
-
subject.update_cart params
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
context "given an order with no existing addresses" do
|
261
|
-
context "when an address is supplied" do
|
262
|
-
let(:updated_address) { build :address, state_code: "CA", zipcode: "14902" }
|
263
|
-
|
264
|
-
let(:params) do
|
265
|
-
{ ship_address_attributes: updated_address.attributes, bill_address_attributes: updated_address.value_attributes }
|
266
|
-
end
|
267
|
-
|
268
|
-
it "does not updates tax adjustments" do
|
269
|
-
expect(subject.order).not_to receive(:create_tax_charge!)
|
270
|
-
subject.update_cart params
|
271
|
-
end
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
259
|
context "submits item quantity 0" do
|
276
260
|
let(:params) do
|
277
261
|
{ line_items_attributes: {
|
@@ -201,12 +201,10 @@ describe Spree::OrderInventory, type: :model do
|
|
201
201
|
end
|
202
202
|
|
203
203
|
it 'should destroy self if not inventory units remain' do
|
204
|
-
shipment.inventory_units
|
205
|
-
shipment.
|
204
|
+
allow(shipment.inventory_units).to receive_messages(count: 0)
|
205
|
+
expect(shipment).to receive(:destroy)
|
206
206
|
|
207
|
-
expect
|
208
|
-
expect(subject.send(:remove_from_shipment, shipment, 1)).to eq(1)
|
209
|
-
}.to change{ order.shipments.count }.from(1).to(0)
|
207
|
+
expect(subject.send(:remove_from_shipment, shipment, 1)).to eq(1)
|
210
208
|
end
|
211
209
|
|
212
210
|
context "inventory unit line item and variant points to different products" do
|
@@ -43,6 +43,26 @@ module Spree
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
+
context 'merging together two orders with multiple currencies line items' do
|
47
|
+
let(:order_2) { Spree::Order.create(currency: 'JPY') }
|
48
|
+
let(:variant_2) { create(:variant) }
|
49
|
+
|
50
|
+
before do
|
51
|
+
Spree::Price.create(variant: variant_2, amount: 10, currency: 'JPY')
|
52
|
+
order_1.contents.add(variant, 1)
|
53
|
+
order_2.contents.add(variant_2.reload, 1)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'rejects other order line items' do
|
57
|
+
subject.merge!(order_2, user)
|
58
|
+
expect(order_1.line_items.count).to eq(1)
|
59
|
+
|
60
|
+
line_item = order_1.line_items.first
|
61
|
+
expect(line_item.quantity).to eq(1)
|
62
|
+
expect(line_item.variant_id).to eq(variant.id)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
46
66
|
context "merging using extension-specific line_item_comparison_hooks" do
|
47
67
|
before do
|
48
68
|
Spree::Order.register_line_item_comparison_hook(:foos_match)
|
@@ -1,11 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
class FakeCalculator < Spree::Calculator
|
4
|
-
def compute(_computable)
|
5
|
-
5
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
3
|
describe Spree::Order, type: :model do
|
10
4
|
let(:store) { build_stubbed(:store) }
|
11
5
|
let(:user) { stub_model(Spree::LegacyUser, email: "spree@example.com") }
|
@@ -516,7 +510,8 @@ describe Spree::Order, type: :model do
|
|
516
510
|
payment_method = Spree::PaymentMethod.create!({
|
517
511
|
name: "Fake",
|
518
512
|
active: true,
|
519
|
-
|
513
|
+
available_to_users: true,
|
514
|
+
available_to_admin: false
|
520
515
|
})
|
521
516
|
expect(order.available_payment_methods).to include(payment_method)
|
522
517
|
end
|
@@ -525,16 +520,18 @@ describe Spree::Order, type: :model do
|
|
525
520
|
payment_method = Spree::PaymentMethod.create!({
|
526
521
|
name: "Fake",
|
527
522
|
active: true,
|
528
|
-
|
523
|
+
available_to_users: true,
|
524
|
+
available_to_admin: true
|
529
525
|
})
|
530
526
|
expect(order.available_payment_methods).to include(payment_method)
|
531
527
|
end
|
532
528
|
|
533
|
-
it "does not include a payment method twice
|
529
|
+
it "does not include a payment method twice" do
|
534
530
|
payment_method = Spree::PaymentMethod.create!({
|
535
531
|
name: "Fake",
|
536
532
|
active: true,
|
537
|
-
|
533
|
+
available_to_users: true,
|
534
|
+
available_to_admin: true
|
538
535
|
})
|
539
536
|
expect(order.available_payment_methods.count).to eq(1)
|
540
537
|
expect(order.available_payment_methods).to include(payment_method)
|
@@ -543,8 +540,10 @@ describe Spree::Order, type: :model do
|
|
543
540
|
context "with more than one payment method" do
|
544
541
|
subject { order.available_payment_methods }
|
545
542
|
|
546
|
-
let!(:first_method) { FactoryGirl.create(:payment_method,
|
547
|
-
|
543
|
+
let!(:first_method) { FactoryGirl.create(:payment_method, available_to_users: true,
|
544
|
+
available_to_admin: true) }
|
545
|
+
let!(:second_method) { FactoryGirl.create(:payment_method, available_to_users: true,
|
546
|
+
available_to_admin: true) }
|
548
547
|
|
549
548
|
before do
|
550
549
|
second_method.move_to_top
|
@@ -575,6 +574,23 @@ describe Spree::Order, type: :model do
|
|
575
574
|
[payment_method_with_store]
|
576
575
|
)
|
577
576
|
end
|
577
|
+
|
578
|
+
context 'and the store has an extra payment method unavailable to users' do
|
579
|
+
let!(:admin_only_payment_method) do create(:payment_method,
|
580
|
+
available_to_users: false,
|
581
|
+
available_to_admin: true)
|
582
|
+
end
|
583
|
+
|
584
|
+
before do
|
585
|
+
store_with_payment_methods.payment_methods << admin_only_payment_method
|
586
|
+
end
|
587
|
+
|
588
|
+
it 'returns only the payment methods available to users for that store' do
|
589
|
+
expect(order.available_payment_methods).to match_array(
|
590
|
+
[payment_method_with_store]
|
591
|
+
)
|
592
|
+
end
|
593
|
+
end
|
578
594
|
end
|
579
595
|
|
580
596
|
context 'when the store does not have payment methods' do
|
@@ -1488,56 +1504,4 @@ describe Spree::Order, type: :model do
|
|
1488
1504
|
end
|
1489
1505
|
end
|
1490
1506
|
end
|
1491
|
-
|
1492
|
-
describe "#validate_payments_attributes" do
|
1493
|
-
let(:attributes) { [ActionController::Parameters.new(payment_method_id: payment_method.id)] }
|
1494
|
-
subject do
|
1495
|
-
order.validate_payments_attributes(attributes)
|
1496
|
-
end
|
1497
|
-
|
1498
|
-
context "with empty array" do
|
1499
|
-
let(:attributes) { [] }
|
1500
|
-
it "doesn't error" do
|
1501
|
-
subject
|
1502
|
-
end
|
1503
|
-
end
|
1504
|
-
|
1505
|
-
context "with no payment method specified" do
|
1506
|
-
let(:attributes) { [ActionController::Parameters.new({})] }
|
1507
|
-
it "doesn't error" do
|
1508
|
-
subject
|
1509
|
-
end
|
1510
|
-
end
|
1511
|
-
|
1512
|
-
context "with valid payment method" do
|
1513
|
-
let(:payment_method) { create(:check_payment_method) }
|
1514
|
-
it "doesn't error" do
|
1515
|
-
subject
|
1516
|
-
end
|
1517
|
-
end
|
1518
|
-
|
1519
|
-
context "with inactive payment method" do
|
1520
|
-
let(:payment_method) { create(:check_payment_method, active: false) }
|
1521
|
-
|
1522
|
-
it "raises RecordNotFound" do
|
1523
|
-
expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
|
1524
|
-
end
|
1525
|
-
end
|
1526
|
-
|
1527
|
-
context "with unavailable payment method" do
|
1528
|
-
let(:payment_method) { create(:check_payment_method, display_on: "back_end") }
|
1529
|
-
|
1530
|
-
it "raises RecordNotFound" do
|
1531
|
-
expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
|
1532
|
-
end
|
1533
|
-
end
|
1534
|
-
|
1535
|
-
context "with soft-deleted payment method" do
|
1536
|
-
let(:payment_method) { create(:check_payment_method, deleted_at: Time.current) }
|
1537
|
-
|
1538
|
-
it "raises RecordNotFound" do
|
1539
|
-
expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
|
1540
|
-
end
|
1541
|
-
end
|
1542
|
-
end
|
1543
1507
|
end
|
@@ -3,7 +3,6 @@ require 'spec_helper'
|
|
3
3
|
module Spree
|
4
4
|
RSpec.describe OrderUpdateAttributes do
|
5
5
|
let(:order) { create(:order) }
|
6
|
-
let(:payment_method) { create(:payment_method) }
|
7
6
|
let(:request_env) { nil }
|
8
7
|
let(:update) { described_class.new(order, attributes, request_env: request_env) }
|
9
8
|
|
@@ -26,10 +25,7 @@ module Spree
|
|
26
25
|
let(:attributes) do
|
27
26
|
{
|
28
27
|
payments_attributes: [
|
29
|
-
{
|
30
|
-
payment_method_id: payment_method.id,
|
31
|
-
source_attributes: attributes_for(:credit_card)
|
32
|
-
}
|
28
|
+
{ source_attributes: attributes_for(:credit_card) }
|
33
29
|
]
|
34
30
|
}
|
35
31
|
end
|
@@ -67,6 +67,257 @@ module Spree
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
+
describe '#recalculate_adjustments ' do
|
71
|
+
describe 'promotion recalculation' do
|
72
|
+
let(:order) { create(:order_with_line_items, line_items_count: 1, line_items_price: 10) }
|
73
|
+
let(:line_item) { order.line_items[0] }
|
74
|
+
|
75
|
+
context 'when the item quantity has changed' do
|
76
|
+
let(:promotion) { create(:promotion, promotion_actions: [promotion_action]) }
|
77
|
+
let(:promotion_action) { Spree::Promotion::Actions::CreateItemAdjustments.new(calculator: calculator) }
|
78
|
+
let(:calculator) { Spree::Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 10) }
|
79
|
+
|
80
|
+
before do
|
81
|
+
promotion.activate(order: order)
|
82
|
+
order.update!
|
83
|
+
line_item.update!(quantity: 2)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'updates the promotion amount' do
|
87
|
+
expect {
|
88
|
+
order.update!
|
89
|
+
}.to change {
|
90
|
+
line_item.promo_total
|
91
|
+
}.from(-1).to(-2)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'promotion chooser customization' do
|
96
|
+
before do
|
97
|
+
class Spree::TestPromotionChooser
|
98
|
+
def initialize(_adjustments)
|
99
|
+
raise 'Custom promotion chooser'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
Spree::Config.promotion_chooser_class = Spree::TestPromotionChooser
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'uses the defined promotion chooser' do
|
107
|
+
expect { order.update! }.to raise_error('Custom promotion chooser')
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'default promotion chooser (best promotion is always applied)' do
|
112
|
+
let(:calculator) { Calculator::FlatRate.new(preferred_amount: 10) }
|
113
|
+
|
114
|
+
let(:source) do
|
115
|
+
Promotion::Actions::CreateItemAdjustments.create!(
|
116
|
+
calculator: calculator,
|
117
|
+
promotion: promotion,
|
118
|
+
)
|
119
|
+
end
|
120
|
+
let(:promotion) { create(:promotion) }
|
121
|
+
|
122
|
+
def create_adjustment(label, amount)
|
123
|
+
create(
|
124
|
+
:adjustment,
|
125
|
+
order: order,
|
126
|
+
adjustable: line_item,
|
127
|
+
source: source,
|
128
|
+
amount: amount,
|
129
|
+
finalized: true,
|
130
|
+
label: label,
|
131
|
+
)
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should make all but the most valuable promotion adjustment ineligible, leaving non promotion adjustments alone' do
|
135
|
+
create_adjustment('Promotion A', -100)
|
136
|
+
create_adjustment('Promotion B', -200)
|
137
|
+
create_adjustment('Promotion C', -300)
|
138
|
+
create(:adjustment, order: order,
|
139
|
+
adjustable: line_item,
|
140
|
+
source: nil,
|
141
|
+
amount: -500,
|
142
|
+
finalized: true,
|
143
|
+
label: 'Some other credit')
|
144
|
+
line_item.adjustments.each { |a| a.update_column(:eligible, true) }
|
145
|
+
|
146
|
+
order.update!
|
147
|
+
|
148
|
+
expect(line_item.adjustments.promotion.eligible.count).to eq(1)
|
149
|
+
expect(line_item.adjustments.promotion.eligible.first.label).to eq('Promotion C')
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should choose the most recent promotion adjustment when amounts are equal' do
|
153
|
+
# Using Timecop is a regression test
|
154
|
+
Timecop.freeze do
|
155
|
+
create_adjustment('Promotion A', -200)
|
156
|
+
create_adjustment('Promotion B', -200)
|
157
|
+
end
|
158
|
+
line_item.adjustments.each { |a| a.update_column(:eligible, true) }
|
159
|
+
|
160
|
+
order.update!
|
161
|
+
|
162
|
+
expect(line_item.adjustments.promotion.eligible.count).to eq(1)
|
163
|
+
expect(line_item.adjustments.promotion.eligible.first.label).to eq('Promotion B')
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should choose the most recent promotion adjustment when amounts are equal' do
|
167
|
+
# Using Timecop is a regression test
|
168
|
+
Timecop.freeze do
|
169
|
+
create_adjustment('Promotion A', -200)
|
170
|
+
create_adjustment('Promotion B', -200)
|
171
|
+
end
|
172
|
+
line_item.adjustments.each { |a| a.update_column(:eligible, true) }
|
173
|
+
|
174
|
+
order.update!
|
175
|
+
|
176
|
+
expect(line_item.adjustments.promotion.eligible.count).to eq(1)
|
177
|
+
expect(line_item.adjustments.promotion.eligible.first.label).to eq('Promotion B')
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'when previously ineligible promotions become available' do
|
181
|
+
let(:order_promo1) { create(:promotion, :with_order_adjustment, :with_item_total_rule, weighted_order_adjustment_amount: 5, item_total_threshold_amount: 10) }
|
182
|
+
let(:order_promo2) { create(:promotion, :with_order_adjustment, :with_item_total_rule, weighted_order_adjustment_amount: 10, item_total_threshold_amount: 20) }
|
183
|
+
let(:order_promos) { [order_promo1, order_promo2] }
|
184
|
+
let(:line_item_promo1) { create(:promotion, :with_line_item_adjustment, :with_item_total_rule, adjustment_rate: 2.5, item_total_threshold_amount: 10, apply_automatically: true) }
|
185
|
+
let(:line_item_promo2) { create(:promotion, :with_line_item_adjustment, :with_item_total_rule, adjustment_rate: 5, item_total_threshold_amount: 20, apply_automatically: true) }
|
186
|
+
let(:line_item_promos) { [line_item_promo1, line_item_promo2] }
|
187
|
+
let(:order) { create(:order_with_line_items, line_items_count: 1) }
|
188
|
+
|
189
|
+
# Apply promotions in different sequences. Results should be the same.
|
190
|
+
promo_sequences = [
|
191
|
+
[0, 1],
|
192
|
+
[1, 0],
|
193
|
+
]
|
194
|
+
|
195
|
+
promo_sequences.each do |promo_sequence|
|
196
|
+
context "with promo sequence #{promo_sequence}" do
|
197
|
+
it 'should pick the best order-level promo according to current eligibility' do
|
198
|
+
# apply both promos to the order, even though only promo1 is eligible
|
199
|
+
order_promos[promo_sequence[0]].activate order: order
|
200
|
+
order_promos[promo_sequence[1]].activate order: order
|
201
|
+
|
202
|
+
order.update!
|
203
|
+
order.reload
|
204
|
+
expect(order.all_adjustments.count).to eq(2), 'Expected two adjustments'
|
205
|
+
expect(order.all_adjustments.eligible.count).to eq(1), 'Expected one elegible adjustment'
|
206
|
+
expect(order.all_adjustments.eligible.first.source.promotion).to eq(order_promo1), 'Expected promo1 to be used'
|
207
|
+
|
208
|
+
order.contents.add create(:variant, price: 10), 1
|
209
|
+
order.save
|
210
|
+
|
211
|
+
order.reload
|
212
|
+
expect(order.all_adjustments.count).to eq(2), 'Expected two adjustments'
|
213
|
+
expect(order.all_adjustments.eligible.count).to eq(1), 'Expected one elegible adjustment'
|
214
|
+
expect(order.all_adjustments.eligible.first.source.promotion).to eq(order_promo2), 'Expected promo2 to be used'
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should pick the best line-item-level promo according to current eligibility' do
|
218
|
+
# apply both promos to the order, even though only promo1 is eligible
|
219
|
+
line_item_promos[promo_sequence[0]].activate order: order
|
220
|
+
line_item_promos[promo_sequence[1]].activate order: order
|
221
|
+
|
222
|
+
order.reload
|
223
|
+
expect(order.all_adjustments.count).to eq(1), 'Expected one adjustment'
|
224
|
+
expect(order.all_adjustments.eligible.count).to eq(1), 'Expected one elegible adjustment'
|
225
|
+
# line_item_promo1 is the only one that has thus far met the order total threshold, it is the only promo which should be applied.
|
226
|
+
expect(order.all_adjustments.first.source.promotion).to eq(line_item_promo1), 'Expected line_item_promo1 to be used'
|
227
|
+
|
228
|
+
order.contents.add create(:variant, price: 10), 1
|
229
|
+
order.save
|
230
|
+
|
231
|
+
order.reload
|
232
|
+
expect(order.all_adjustments.count).to eq(4), 'Expected four adjustments'
|
233
|
+
expect(order.all_adjustments.eligible.count).to eq(2), 'Expected two elegible adjustments'
|
234
|
+
order.all_adjustments.eligible.each do |adjustment|
|
235
|
+
expect(adjustment.source.promotion).to eq(line_item_promo2), 'Expected line_item_promo2 to be used'
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
context 'multiple adjustments and the best one is not eligible' do
|
243
|
+
let!(:promo_a) { create_adjustment('Promotion A', -100) }
|
244
|
+
let!(:promo_c) { create_adjustment('Promotion C', -300) }
|
245
|
+
|
246
|
+
before do
|
247
|
+
promo_a.update_column(:eligible, true)
|
248
|
+
promo_c.update_column(:eligible, false)
|
249
|
+
end
|
250
|
+
|
251
|
+
# regression for https://github.com/spree/spree/issues/3274
|
252
|
+
it 'still makes the previous best eligible adjustment valid' do
|
253
|
+
order.update!
|
254
|
+
expect(line_item.adjustments.promotion.eligible.first.label).to eq('Promotion A')
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'should only leave one adjustment even if 2 have the same amount' do
|
259
|
+
create_adjustment('Promotion A', -100)
|
260
|
+
create_adjustment('Promotion B', -200)
|
261
|
+
create_adjustment('Promotion C', -200)
|
262
|
+
|
263
|
+
order.update!
|
264
|
+
|
265
|
+
expect(line_item.adjustments.promotion.eligible.count).to eq(1)
|
266
|
+
expect(line_item.adjustments.promotion.eligible.first.amount.to_i).to eq(-200)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
describe 'tax recalculation' do
|
272
|
+
let!(:ship_address) { create(:address) }
|
273
|
+
let!(:tax_zone) { create(:global_zone) } # will include the above address
|
274
|
+
let!(:tax_rate) { create(:tax_rate, zone: tax_zone, tax_category: tax_category) }
|
275
|
+
|
276
|
+
let(:order) do
|
277
|
+
create(
|
278
|
+
:order_with_line_items,
|
279
|
+
line_items_attributes: [{ price: 10, variant: variant }],
|
280
|
+
ship_address: ship_address,
|
281
|
+
)
|
282
|
+
end
|
283
|
+
let(:line_item) { order.line_items[0] }
|
284
|
+
|
285
|
+
let(:variant) { create(:variant, tax_category: tax_category) }
|
286
|
+
let(:tax_category) { create(:tax_category) }
|
287
|
+
|
288
|
+
context 'when the item quantity has changed' do
|
289
|
+
before do
|
290
|
+
line_item.update!(quantity: 2)
|
291
|
+
end
|
292
|
+
|
293
|
+
it 'updates the promotion amount' do
|
294
|
+
expect {
|
295
|
+
order.update!
|
296
|
+
}.to change {
|
297
|
+
line_item.additional_tax_total
|
298
|
+
}.from(1).to(2)
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
context 'with a custom tax_adjuster_class' do
|
303
|
+
let(:custom_adjuster_class) { double }
|
304
|
+
let(:custom_adjuster_instance) { double }
|
305
|
+
|
306
|
+
before do
|
307
|
+
order # generate this first so we can expect it
|
308
|
+
Spree::Config.tax_adjuster_class = custom_adjuster_class
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'uses the configured class' do
|
312
|
+
expect(custom_adjuster_class).to receive(:new).with(order).at_least(:once).and_return(custom_adjuster_instance)
|
313
|
+
expect(custom_adjuster_instance).to receive(:adjust!).at_least(:once)
|
314
|
+
|
315
|
+
order.update!
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
70
321
|
context "updating shipment state" do
|
71
322
|
before do
|
72
323
|
allow(order).to receive_messages backordered?: false
|