spree_core 3.0.5 → 3.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile +3 -0
- data/Rakefile +30 -0
- data/app/assets/javascripts/spree.js.coffee.erb +1 -1
- data/app/models/spree/ability.rb +1 -1
- data/app/models/spree/base.rb +3 -1
- data/app/models/spree/order_updater.rb +2 -1
- data/app/models/spree/price.rb +7 -12
- data/app/models/spree/product.rb +3 -2
- data/app/models/spree/reimbursement.rb +1 -1
- data/app/models/spree/state.rb +2 -0
- data/app/models/spree/zone.rb +1 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/testing_support/shoulda_matcher_configuration.rb +6 -0
- data/script/rails +9 -0
- data/spec/fixtures/thinking-cat.jpg +0 -0
- data/spec/helpers/base_helper_spec.rb +137 -0
- data/spec/helpers/products_helper_spec.rb +224 -0
- data/spec/lib/calculated_adjustments_spec.rb +7 -0
- data/spec/lib/i18n_spec.rb +123 -0
- data/spec/lib/search/base_spec.rb +86 -0
- data/spec/lib/spree/core/controller_helpers/auth_spec.rb +101 -0
- data/spec/lib/spree/core/controller_helpers/order_spec.rb +95 -0
- data/spec/lib/spree/core/controller_helpers/search_spec.rb +17 -0
- data/spec/lib/spree/core/controller_helpers/store_spec.rb +16 -0
- data/spec/lib/spree/core/controller_helpers/strong_parameters_spec.rb +39 -0
- data/spec/lib/spree/core/delegate_belongs_to_spec.rb +22 -0
- data/spec/lib/spree/core/importer/order_spec.rb +502 -0
- data/spec/lib/spree/core/validators/email_spec.rb +53 -0
- data/spec/lib/spree/localized_number_spec.rb +38 -0
- data/spec/lib/spree/migrations_spec.rb +34 -0
- data/spec/lib/spree/money_spec.rb +122 -0
- data/spec/lib/tasks/exchanges_spec.rb +136 -0
- data/spec/mailers/order_mailer_spec.rb +124 -0
- data/spec/mailers/reimbursement_mailer_spec.rb +47 -0
- data/spec/mailers/shipment_mailer_spec.rb +63 -0
- data/spec/mailers/test_mailer_spec.rb +24 -0
- data/spec/models/spree/ability_spec.rb +246 -0
- data/spec/models/spree/address_spec.rb +291 -0
- data/spec/models/spree/adjustable/adjustments_updater_spec.rb +286 -0
- data/spec/models/spree/adjustment_spec.rb +163 -0
- data/spec/models/spree/app_configuration_spec.rb +23 -0
- data/spec/models/spree/asset_spec.rb +25 -0
- data/spec/models/spree/calculator/default_tax_spec.rb +127 -0
- data/spec/models/spree/calculator/flat_percent_item_total_spec.rb +25 -0
- data/spec/models/spree/calculator/flat_rate_spec.rb +47 -0
- data/spec/models/spree/calculator/flexi_rate_spec.rb +41 -0
- data/spec/models/spree/calculator/percent_on_line_item_spec.rb +15 -0
- data/spec/models/spree/calculator/price_sack_spec.rb +30 -0
- data/spec/models/spree/calculator/refunds/default_refund_amount_spec.rb +51 -0
- data/spec/models/spree/calculator/shipping.rb +8 -0
- data/spec/models/spree/calculator/shipping/flat_percent_item_total_spec.rb +23 -0
- data/spec/models/spree/calculator/shipping/flat_rate_spec.rb +13 -0
- data/spec/models/spree/calculator/shipping/flexi_rate_spec.rb +52 -0
- data/spec/models/spree/calculator/shipping/per_item_spec.rb +20 -0
- data/spec/models/spree/calculator/shipping/price_sack_spec.rb +29 -0
- data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +40 -0
- data/spec/models/spree/calculator/tiered_percent_spec.rb +51 -0
- data/spec/models/spree/calculator_spec.rb +69 -0
- data/spec/models/spree/classification_spec.rb +93 -0
- data/spec/models/spree/concerns/display_money_spec.rb +43 -0
- data/spec/models/spree/country_spec.rb +18 -0
- data/spec/models/spree/credit_card_spec.rb +324 -0
- data/spec/models/spree/customer_return_spec.rb +262 -0
- data/spec/models/spree/exchange_spec.rb +75 -0
- data/spec/models/spree/gateway/bogus_simple.rb +20 -0
- data/spec/models/spree/gateway/bogus_spec.rb +13 -0
- data/spec/models/spree/gateway_spec.rb +54 -0
- data/spec/models/spree/image_spec.rb +5 -0
- data/spec/models/spree/inventory_unit_spec.rb +242 -0
- data/spec/models/spree/line_item_spec.rb +267 -0
- data/spec/models/spree/option_type_spec.rb +14 -0
- data/spec/models/spree/option_value_spec.rb +13 -0
- data/spec/models/spree/order/address_spec.rb +50 -0
- data/spec/models/spree/order/adjustments_spec.rb +29 -0
- data/spec/models/spree/order/callbacks_spec.rb +42 -0
- data/spec/models/spree/order/checkout_spec.rb +764 -0
- data/spec/models/spree/order/currency_updater_spec.rb +32 -0
- data/spec/models/spree/order/finalizing_spec.rb +117 -0
- data/spec/models/spree/order/helpers_spec.rb +5 -0
- data/spec/models/spree/order/payment_spec.rb +214 -0
- data/spec/models/spree/order/risk_assessment_spec.rb +84 -0
- data/spec/models/spree/order/shipments_spec.rb +43 -0
- data/spec/models/spree/order/state_machine_spec.rb +216 -0
- data/spec/models/spree/order/tax_spec.rb +84 -0
- data/spec/models/spree/order/totals_spec.rb +24 -0
- data/spec/models/spree/order/updating_spec.rb +18 -0
- data/spec/models/spree/order/validations_spec.rb +15 -0
- data/spec/models/spree/order_contents_spec.rb +256 -0
- data/spec/models/spree/order_inventory_spec.rb +228 -0
- data/spec/models/spree/order_merger_spec.rb +133 -0
- data/spec/models/spree/order_spec.rb +954 -0
- data/spec/models/spree/order_updater_spec.rb +283 -0
- data/spec/models/spree/payment/gateway_options_spec.rb +119 -0
- data/spec/models/spree/payment_method_spec.rb +95 -0
- data/spec/models/spree/payment_spec.rb +926 -0
- data/spec/models/spree/preference_spec.rb +80 -0
- data/spec/models/spree/preferences/configuration_spec.rb +30 -0
- data/spec/models/spree/preferences/preferable_spec.rb +348 -0
- data/spec/models/spree/preferences/scoped_store_spec.rb +58 -0
- data/spec/models/spree/preferences/store_spec.rb +46 -0
- data/spec/models/spree/price_spec.rb +42 -0
- data/spec/models/spree/product/scopes_spec.rb +148 -0
- data/spec/models/spree/product_duplicator_spec.rb +103 -0
- data/spec/models/spree/product_filter_spec.rb +26 -0
- data/spec/models/spree/product_option_type_spec.rb +5 -0
- data/spec/models/spree/product_property_spec.rb +11 -0
- data/spec/models/spree/product_spec.rb +474 -0
- data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +50 -0
- data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +148 -0
- data/spec/models/spree/promotion/actions/create_line_items_spec.rb +86 -0
- data/spec/models/spree/promotion/actions/free_shipping_spec.rb +36 -0
- data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
- data/spec/models/spree/promotion/rules/item_total_spec.rb +282 -0
- data/spec/models/spree/promotion/rules/one_use_per_user_spec.rb +42 -0
- data/spec/models/spree/promotion/rules/option_value_spec.rb +90 -0
- data/spec/models/spree/promotion/rules/product_spec.rb +143 -0
- data/spec/models/spree/promotion/rules/taxon_spec.rb +102 -0
- data/spec/models/spree/promotion/rules/user_logged_in_spec.rb +27 -0
- data/spec/models/spree/promotion/rules/user_spec.rb +37 -0
- data/spec/models/spree/promotion_action_spec.rb +10 -0
- data/spec/models/spree/promotion_category_spec.rb +17 -0
- data/spec/models/spree/promotion_handler/cart_spec.rb +102 -0
- data/spec/models/spree/promotion_handler/coupon_spec.rb +323 -0
- data/spec/models/spree/promotion_handler/free_shipping_spec.rb +48 -0
- data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
- data/spec/models/spree/promotion_rule_spec.rb +29 -0
- data/spec/models/spree/promotion_spec.rb +603 -0
- data/spec/models/spree/property_spec.rb +5 -0
- data/spec/models/spree/prototype_spec.rb +5 -0
- data/spec/models/spree/refund_spec.rb +195 -0
- data/spec/models/spree/reimbursement/credit_spec.rb +36 -0
- data/spec/models/spree/reimbursement/reimbursement_type_engine_spec.rb +140 -0
- data/spec/models/spree/reimbursement/reimbursement_type_validator_spec.rb +83 -0
- data/spec/models/spree/reimbursement_performer_spec.rb +30 -0
- data/spec/models/spree/reimbursement_spec.rb +215 -0
- data/spec/models/spree/reimbursement_tax_calculator_spec.rb +51 -0
- data/spec/models/spree/reimbursement_type/credit_spec.rb +53 -0
- data/spec/models/spree/reimbursement_type/exchange_spec.rb +46 -0
- data/spec/models/spree/reimbursement_type/original_payment_spec.rb +55 -0
- data/spec/models/spree/return_authorization_spec.rb +250 -0
- data/spec/models/spree/return_item/eligibility_validator/default_spec.rb +77 -0
- data/spec/models/spree/return_item/eligibility_validator/inventory_shipped_spec.rb +58 -0
- data/spec/models/spree/return_item/eligibility_validator/no_reimbursements_spec.rb +61 -0
- data/spec/models/spree/return_item/eligibility_validator/order_completed_spec.rb +32 -0
- data/spec/models/spree/return_item/eligibility_validator/rma_required_spec.rb +29 -0
- data/spec/models/spree/return_item/eligibility_validator/time_since_purchase_spec.rb +35 -0
- data/spec/models/spree/return_item/exchange_variant_eligibility/same_option_value_spec.rb +65 -0
- data/spec/models/spree/return_item/exchange_variant_eligibility/same_product_spec.rb +43 -0
- data/spec/models/spree/return_item_spec.rb +682 -0
- data/spec/models/spree/returns_calculator_spec.rb +14 -0
- data/spec/models/spree/shipment_spec.rb +740 -0
- data/spec/models/spree/shipping_calculator_spec.rb +45 -0
- data/spec/models/spree/shipping_category_spec.rb +5 -0
- data/spec/models/spree/shipping_method_spec.rb +88 -0
- data/spec/models/spree/shipping_rate_spec.rb +141 -0
- data/spec/models/spree/state_spec.rb +18 -0
- data/spec/models/spree/stock/availability_validator_spec.rb +36 -0
- data/spec/models/spree/stock/content_item_spec.rb +22 -0
- data/spec/models/spree/stock/coordinator_spec.rb +51 -0
- data/spec/models/spree/stock/differentiator_spec.rb +39 -0
- data/spec/models/spree/stock/estimator_spec.rb +154 -0
- data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
- data/spec/models/spree/stock/package_spec.rb +194 -0
- data/spec/models/spree/stock/packer_spec.rb +70 -0
- data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
- data/spec/models/spree/stock/quantifier_spec.rb +97 -0
- data/spec/models/spree/stock/splitter/backordered_spec.rb +29 -0
- data/spec/models/spree/stock/splitter/base_spec.rb +21 -0
- data/spec/models/spree/stock/splitter/shipping_category_spec.rb +47 -0
- data/spec/models/spree/stock/splitter/weight_spec.rb +32 -0
- data/spec/models/spree/stock_item_spec.rb +410 -0
- data/spec/models/spree/stock_location_spec.rb +243 -0
- data/spec/models/spree/stock_movement_spec.rb +56 -0
- data/spec/models/spree/stock_transfer_spec.rb +50 -0
- data/spec/models/spree/store_spec.rb +50 -0
- data/spec/models/spree/tax_category_spec.rb +27 -0
- data/spec/models/spree/tax_rate_spec.rb +382 -0
- data/spec/models/spree/taxon_spec.rb +74 -0
- data/spec/models/spree/taxonomy_spec.rb +18 -0
- data/spec/models/spree/tracker_spec.rb +21 -0
- data/spec/models/spree/user_spec.rb +130 -0
- data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +24 -0
- data/spec/models/spree/variant_spec.rb +523 -0
- data/spec/models/spree/zone_spec.rb +444 -0
- data/spec/spec_helper.rb +74 -0
- data/spec/support/big_decimal.rb +5 -0
- data/spec/support/concerns/adjustment_source_spec.rb +23 -0
- data/spec/support/concerns/default_price_spec.rb +28 -0
- data/spec/support/rake.rb +13 -0
- data/spec/support/test_gateway.rb +2 -0
- data/spree_core.gemspec +48 -0
- metadata +185 -4
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::OrderInventory, :type => :model do
|
|
4
|
+
let(:order) { create :completed_order_with_totals }
|
|
5
|
+
let(:line_item) { order.line_items.first }
|
|
6
|
+
|
|
7
|
+
subject { described_class.new(order, line_item) }
|
|
8
|
+
|
|
9
|
+
context "when order is missing inventory units" do
|
|
10
|
+
before { line_item.update_column(:quantity, 2) }
|
|
11
|
+
|
|
12
|
+
it 'creates the proper number of inventory units' do
|
|
13
|
+
subject.verify
|
|
14
|
+
expect(subject.inventory_units.count).to eq 2
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context "#add_to_shipment" do
|
|
19
|
+
let(:shipment) { order.shipments.first }
|
|
20
|
+
|
|
21
|
+
context "order is not completed" do
|
|
22
|
+
before { allow(order).to receive_messages completed?: false }
|
|
23
|
+
|
|
24
|
+
it "doesn't unstock items" do
|
|
25
|
+
expect(shipment.stock_location).not_to receive(:unstock)
|
|
26
|
+
expect(subject.send(:add_to_shipment, shipment, 5)).to eq(5)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context "inventory units state" do
|
|
31
|
+
before { shipment.inventory_units.destroy_all }
|
|
32
|
+
|
|
33
|
+
it 'sets inventory_units state as per stock location availability' do
|
|
34
|
+
expect(shipment.stock_location).to receive(:fill_status).with(subject.variant, 5).and_return([3, 2])
|
|
35
|
+
|
|
36
|
+
expect(subject.send(:add_to_shipment, shipment, 5)).to eq(5)
|
|
37
|
+
|
|
38
|
+
units = shipment.inventory_units_for(subject.variant).group_by(&:state)
|
|
39
|
+
expect(units['backordered'].size).to eq(2)
|
|
40
|
+
expect(units['on_hand'].size).to eq(3)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context "store doesnt track inventory" do
|
|
45
|
+
let(:variant) { create(:variant) }
|
|
46
|
+
|
|
47
|
+
before { Spree::Config.track_inventory_levels = false }
|
|
48
|
+
|
|
49
|
+
it "creates only on hand inventory units" do
|
|
50
|
+
variant.stock_items.destroy_all
|
|
51
|
+
|
|
52
|
+
# The before_save callback in LineItem would verify inventory
|
|
53
|
+
line_item = order.contents.add variant, 1, shipment: shipment
|
|
54
|
+
|
|
55
|
+
units = shipment.inventory_units_for(line_item.variant)
|
|
56
|
+
expect(units.count).to eq 1
|
|
57
|
+
expect(units.first).to be_on_hand
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "variant doesnt track inventory" do
|
|
62
|
+
let(:variant) { create(:variant) }
|
|
63
|
+
before { variant.track_inventory = false }
|
|
64
|
+
|
|
65
|
+
it "creates only on hand inventory units" do
|
|
66
|
+
variant.stock_items.destroy_all
|
|
67
|
+
|
|
68
|
+
line_item = order.contents.add variant, 1
|
|
69
|
+
subject.verify(shipment)
|
|
70
|
+
|
|
71
|
+
units = shipment.inventory_units_for(line_item.variant)
|
|
72
|
+
expect(units.count).to eq 1
|
|
73
|
+
expect(units.first).to be_on_hand
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'should create stock_movement' do
|
|
78
|
+
expect(subject.send(:add_to_shipment, shipment, 5)).to eq(5)
|
|
79
|
+
|
|
80
|
+
stock_item = shipment.stock_location.stock_item(subject.variant)
|
|
81
|
+
movement = stock_item.stock_movements.last
|
|
82
|
+
# movement.originator.should == shipment
|
|
83
|
+
expect(movement.quantity).to eq(-5)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context "#determine_target_shipment" do
|
|
88
|
+
let(:stock_location) { create :stock_location }
|
|
89
|
+
let(:variant) { line_item.variant }
|
|
90
|
+
|
|
91
|
+
before do
|
|
92
|
+
subject.verify
|
|
93
|
+
|
|
94
|
+
order.shipments.create(:stock_location_id => stock_location.id, :cost => 5)
|
|
95
|
+
|
|
96
|
+
shipped = order.shipments.create(:stock_location_id => order.shipments.first.stock_location.id, :cost => 10)
|
|
97
|
+
shipped.update_column(:state, 'shipped')
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'should select first non-shipped shipment that already contains given variant' do
|
|
101
|
+
shipment = subject.send(:determine_target_shipment)
|
|
102
|
+
expect(shipment.shipped?).to be false
|
|
103
|
+
expect(shipment.inventory_units_for(variant)).not_to be_empty
|
|
104
|
+
|
|
105
|
+
expect(variant.stock_location_ids.include?(shipment.stock_location_id)).to be true
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context "when no shipments already contain this varint" do
|
|
109
|
+
before do
|
|
110
|
+
subject.line_item.reload
|
|
111
|
+
subject.inventory_units.destroy_all
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'selects first non-shipped shipment that leaves from same stock_location' do
|
|
115
|
+
shipment = subject.send(:determine_target_shipment)
|
|
116
|
+
shipment.reload
|
|
117
|
+
expect(shipment.shipped?).to be false
|
|
118
|
+
expect(shipment.inventory_units_for(variant)).to be_empty
|
|
119
|
+
expect(variant.stock_location_ids.include?(shipment.stock_location_id)).to be true
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context 'when order has too many inventory units' do
|
|
125
|
+
before do
|
|
126
|
+
line_item.quantity = 3
|
|
127
|
+
line_item.save!
|
|
128
|
+
|
|
129
|
+
line_item.update_column(:quantity, 2)
|
|
130
|
+
subject.line_item.reload
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it 'should be a messed up order' do
|
|
134
|
+
expect(order.shipments.first.inventory_units_for(line_item.variant).size).to eq(3)
|
|
135
|
+
expect(line_item.quantity).to eq(2)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it 'should decrease the number of inventory units' do
|
|
139
|
+
subject.verify
|
|
140
|
+
expect(subject.inventory_units.count).to eq 2
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context '#remove_from_shipment' do
|
|
144
|
+
let(:shipment) { order.shipments.first }
|
|
145
|
+
let(:variant) { subject.variant }
|
|
146
|
+
|
|
147
|
+
context "order is not completed" do
|
|
148
|
+
before { allow(order).to receive_messages completed?: false }
|
|
149
|
+
|
|
150
|
+
it "doesn't restock items" do
|
|
151
|
+
expect(shipment.stock_location).not_to receive(:restock)
|
|
152
|
+
expect(subject.send(:remove_from_shipment, shipment, 1)).to eq(1)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it 'should create stock_movement' do
|
|
157
|
+
expect(subject.send(:remove_from_shipment, shipment, 1)).to eq(1)
|
|
158
|
+
|
|
159
|
+
stock_item = shipment.stock_location.stock_item(variant)
|
|
160
|
+
movement = stock_item.stock_movements.last
|
|
161
|
+
# movement.originator.should == shipment
|
|
162
|
+
expect(movement.quantity).to eq(1)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it 'should destroy backordered units first' do
|
|
166
|
+
allow(shipment).to receive_messages(inventory_units_for_item: [
|
|
167
|
+
mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'backordered'),
|
|
168
|
+
mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'on_hand'),
|
|
169
|
+
mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'backordered')
|
|
170
|
+
])
|
|
171
|
+
|
|
172
|
+
expect(shipment.inventory_units_for_item[0]).to receive(:destroy)
|
|
173
|
+
expect(shipment.inventory_units_for_item[1]).not_to receive(:destroy)
|
|
174
|
+
expect(shipment.inventory_units_for_item[2]).to receive(:destroy)
|
|
175
|
+
|
|
176
|
+
expect(subject.send(:remove_from_shipment, shipment, 2)).to eq(2)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it 'should destroy unshipped units first' do
|
|
180
|
+
allow(shipment).to receive_messages(inventory_units_for_item: [
|
|
181
|
+
mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'shipped'),
|
|
182
|
+
mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'on_hand')
|
|
183
|
+
])
|
|
184
|
+
|
|
185
|
+
expect(shipment.inventory_units_for_item[0]).not_to receive(:destroy)
|
|
186
|
+
expect(shipment.inventory_units_for_item[1]).to receive(:destroy)
|
|
187
|
+
|
|
188
|
+
expect(subject.send(:remove_from_shipment, shipment, 1)).to eq(1)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it 'only attempts to destroy as many units as are eligible, and return amount destroyed' do
|
|
192
|
+
allow(shipment).to receive_messages(inventory_units_for_item: [
|
|
193
|
+
mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'shipped'),
|
|
194
|
+
mock_model(Spree::InventoryUnit, :variant_id => variant.id, :state => 'on_hand')
|
|
195
|
+
])
|
|
196
|
+
|
|
197
|
+
expect(shipment.inventory_units_for_item[0]).not_to receive(:destroy)
|
|
198
|
+
expect(shipment.inventory_units_for_item[1]).to receive(:destroy)
|
|
199
|
+
|
|
200
|
+
expect(subject.send(:remove_from_shipment, shipment, 1)).to eq(1)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it 'should destroy self if not inventory units remain' do
|
|
204
|
+
allow(shipment.inventory_units).to receive_messages(:count => 0)
|
|
205
|
+
expect(shipment).to receive(:destroy)
|
|
206
|
+
|
|
207
|
+
expect(subject.send(:remove_from_shipment, shipment, 1)).to eq(1)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
context "inventory unit line item and variant points to different products" do
|
|
211
|
+
let(:different_line_item) { create(:line_item) }
|
|
212
|
+
|
|
213
|
+
let!(:different_inventory) do
|
|
214
|
+
shipment.set_up_inventory("on_hand", variant, order, different_line_item)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
context "completed order" do
|
|
218
|
+
before { order.touch :completed_at }
|
|
219
|
+
|
|
220
|
+
it "removes only units that match both line item and variant" do
|
|
221
|
+
subject.send(:remove_from_shipment, shipment, shipment.inventory_units.count)
|
|
222
|
+
expect(different_inventory.reload).to be_persisted
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
# Regression tests for #2179
|
|
4
|
+
module Spree
|
|
5
|
+
describe OrderMerger, type: :model do
|
|
6
|
+
let(:variant) { create(:variant) }
|
|
7
|
+
let(:order_1) { Spree::Order.create }
|
|
8
|
+
let(:order_2) { Spree::Order.create }
|
|
9
|
+
let(:user) { stub_model(Spree::LegacyUser, email: "spree@example.com") }
|
|
10
|
+
let(:subject) { Spree::OrderMerger.new(order_1) }
|
|
11
|
+
|
|
12
|
+
it "destroys the other order" do
|
|
13
|
+
subject.merge!(order_2)
|
|
14
|
+
expect { order_2.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "persist the merge" do
|
|
18
|
+
expect(subject).to receive(:persist_merge)
|
|
19
|
+
subject.merge!(order_2)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "user is provided" do
|
|
23
|
+
it "assigns user to new order" do
|
|
24
|
+
subject.merge!(order_2, user)
|
|
25
|
+
expect(order_1.user).to eq user
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context "merging together two orders with line items for the same variant" do
|
|
30
|
+
before do
|
|
31
|
+
order_1.contents.add(variant, 1)
|
|
32
|
+
order_2.contents.add(variant, 1)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
specify do
|
|
36
|
+
subject.merge!(order_2, user)
|
|
37
|
+
expect(order_1.line_items.count).to eq(1)
|
|
38
|
+
|
|
39
|
+
line_item = order_1.line_items.first
|
|
40
|
+
expect(line_item.quantity).to eq(2)
|
|
41
|
+
expect(line_item.variant_id).to eq(variant.id)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context "merging using extension-specific line_item_comparison_hooks" do
|
|
46
|
+
before do
|
|
47
|
+
Spree::Order.register_line_item_comparison_hook(:foos_match)
|
|
48
|
+
allow(Spree::Variant).to receive(:price_modifier_amount).and_return(0.00)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
after do
|
|
52
|
+
# reset to avoid test pollution
|
|
53
|
+
Spree::Order.line_item_comparison_hooks = Set.new
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "2 equal line items" do
|
|
57
|
+
before do
|
|
58
|
+
@line_item_1 = order_1.contents.add(variant, 1, foos: {})
|
|
59
|
+
@line_item_2 = order_2.contents.add(variant, 1, foos: {})
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
specify do
|
|
63
|
+
expect(order_1).to receive(:foos_match).with(@line_item_1, kind_of(Hash)).and_return(true)
|
|
64
|
+
subject.merge!(order_2)
|
|
65
|
+
expect(order_1.line_items.count).to eq(1)
|
|
66
|
+
|
|
67
|
+
line_item = order_1.line_items.first
|
|
68
|
+
expect(line_item.quantity).to eq(2)
|
|
69
|
+
expect(line_item.variant_id).to eq(variant.id)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "2 different line items" do
|
|
74
|
+
before do
|
|
75
|
+
allow(order_1).to receive(:foos_match).and_return(false)
|
|
76
|
+
|
|
77
|
+
order_1.contents.add(variant, 1, foos: {})
|
|
78
|
+
order_2.contents.add(variant, 1, foos: { bar: :zoo })
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
specify do
|
|
82
|
+
subject.merge!(order_2)
|
|
83
|
+
expect(order_1.line_items.count).to eq(2)
|
|
84
|
+
|
|
85
|
+
line_item = order_1.line_items.first
|
|
86
|
+
expect(line_item.quantity).to eq(1)
|
|
87
|
+
expect(line_item.variant_id).to eq(variant.id)
|
|
88
|
+
|
|
89
|
+
line_item = order_1.line_items.last
|
|
90
|
+
expect(line_item.quantity).to eq(1)
|
|
91
|
+
expect(line_item.variant_id).to eq(variant.id)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context "merging together two orders with different line items" do
|
|
97
|
+
let(:variant_2) { create(:variant) }
|
|
98
|
+
|
|
99
|
+
before do
|
|
100
|
+
order_1.contents.add(variant, 1)
|
|
101
|
+
order_2.contents.add(variant_2, 1)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
specify do
|
|
105
|
+
subject.merge!(order_2)
|
|
106
|
+
line_items = order_1.line_items.reload
|
|
107
|
+
expect(line_items.count).to eq(2)
|
|
108
|
+
|
|
109
|
+
expect(order_1.item_count).to eq 2
|
|
110
|
+
expect(order_1.item_total).to eq line_items.map(&:amount).sum
|
|
111
|
+
|
|
112
|
+
# No guarantee on ordering of line items, so we do this:
|
|
113
|
+
expect(line_items.pluck(:quantity)).to match_array([1, 1])
|
|
114
|
+
expect(line_items.pluck(:variant_id)).to match_array([variant.id, variant_2.id])
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
context "merging together orders with invalid line items" do
|
|
119
|
+
let(:variant_2) { create(:variant) }
|
|
120
|
+
|
|
121
|
+
before do
|
|
122
|
+
order_1.contents.add(variant, 1)
|
|
123
|
+
order_2.contents.add(variant_2, 1)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "should create errors with invalid line items" do
|
|
127
|
+
variant_2.destroy
|
|
128
|
+
subject.merge!(order_2)
|
|
129
|
+
expect(order_1.errors.full_messages).not_to be_empty
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,954 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class FakeCalculator < Spree::Calculator
|
|
4
|
+
def compute(computable)
|
|
5
|
+
5
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe Spree::Order, :type => :model do
|
|
10
|
+
let(:user) { stub_model(Spree::LegacyUser, :email => "spree@example.com") }
|
|
11
|
+
let(:order) { stub_model(Spree::Order, :user => user) }
|
|
12
|
+
|
|
13
|
+
before do
|
|
14
|
+
create(:store)
|
|
15
|
+
allow(Spree::LegacyUser).to receive_messages(:current => mock_model(Spree::LegacyUser, :id => 123))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context "#cancel" do
|
|
19
|
+
let(:order) { create(:completed_order_with_totals) }
|
|
20
|
+
let!(:payment) do
|
|
21
|
+
create(
|
|
22
|
+
:payment,
|
|
23
|
+
order: order,
|
|
24
|
+
amount: order.total,
|
|
25
|
+
state: "completed"
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
let(:payment_method) { double }
|
|
29
|
+
|
|
30
|
+
it "should mark the payments as void" do
|
|
31
|
+
allow_any_instance_of(Spree::Shipment).to receive(:refresh_rates).and_return(true)
|
|
32
|
+
order.cancel
|
|
33
|
+
order.reload
|
|
34
|
+
|
|
35
|
+
expect(order.payments.first).to be_void
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "#canceled_by" do
|
|
40
|
+
let(:admin_user) { create :admin_user }
|
|
41
|
+
let(:order) { create :order }
|
|
42
|
+
|
|
43
|
+
before do
|
|
44
|
+
allow(order).to receive(:cancel!)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
subject { order.canceled_by(admin_user) }
|
|
48
|
+
|
|
49
|
+
it 'should cancel the order' do
|
|
50
|
+
expect(order).to receive(:cancel!)
|
|
51
|
+
subject
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'should save canceler_id' do
|
|
55
|
+
subject
|
|
56
|
+
expect(order.reload.canceler_id).to eq(admin_user.id)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'should save canceled_at' do
|
|
60
|
+
subject
|
|
61
|
+
expect(order.reload.canceled_at).to_not be_nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'should have canceler' do
|
|
65
|
+
subject
|
|
66
|
+
expect(order.reload.canceler).to eq(admin_user)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context "#create" do
|
|
71
|
+
let(:order) { Spree::Order.create }
|
|
72
|
+
|
|
73
|
+
it "should assign an order number" do
|
|
74
|
+
expect(order.number).not_to be_nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'should create a randomized 22 character token' do
|
|
78
|
+
expect(order.guest_token.size).to eq(22)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context "creates shipments cost" do
|
|
83
|
+
let(:shipment) { double }
|
|
84
|
+
|
|
85
|
+
before { allow(order).to receive_messages shipments: [shipment] }
|
|
86
|
+
|
|
87
|
+
it "update and persist totals" do
|
|
88
|
+
expect(shipment).to receive :update_amounts
|
|
89
|
+
expect(order.updater).to receive :update_shipment_total
|
|
90
|
+
expect(order.updater).to receive :persist_totals
|
|
91
|
+
|
|
92
|
+
order.set_shipments_cost
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context "#finalize!" do
|
|
97
|
+
let(:order) { Spree::Order.create(email: 'test@example.com') }
|
|
98
|
+
|
|
99
|
+
before do
|
|
100
|
+
order.update_column :state, 'complete'
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "should set completed_at" do
|
|
104
|
+
expect(order).to receive(:touch).with(:completed_at)
|
|
105
|
+
order.finalize!
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should sell inventory units" do
|
|
109
|
+
order.shipments.each do |shipment|
|
|
110
|
+
expect(shipment).to receive(:update!)
|
|
111
|
+
expect(shipment).to receive(:finalize!)
|
|
112
|
+
end
|
|
113
|
+
order.finalize!
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "should decrease the stock for each variant in the shipment" do
|
|
117
|
+
order.shipments.each do |shipment|
|
|
118
|
+
expect(shipment.stock_location).to receive(:decrease_stock_for_variant)
|
|
119
|
+
end
|
|
120
|
+
order.finalize!
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "should change the shipment state to ready if order is paid" do
|
|
124
|
+
Spree::Shipment.create(order: order, stock_location: create(:stock_location))
|
|
125
|
+
order.shipments.reload
|
|
126
|
+
|
|
127
|
+
allow(order).to receive_messages(paid?: true, complete?: true)
|
|
128
|
+
order.finalize!
|
|
129
|
+
order.reload # reload so we're sure the changes are persisted
|
|
130
|
+
expect(order.shipment_state).to eq('ready')
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
after { Spree::Config.set track_inventory_levels: true }
|
|
134
|
+
it "should not sell inventory units if track_inventory_levels is false" do
|
|
135
|
+
Spree::Config.set track_inventory_levels: false
|
|
136
|
+
expect(Spree::InventoryUnit).not_to receive(:sell_units)
|
|
137
|
+
order.finalize!
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "should send an order confirmation email" do
|
|
141
|
+
mail_message = double "Mail::Message"
|
|
142
|
+
expect(Spree::OrderMailer).to receive(:confirm_email).with(order.id).and_return mail_message
|
|
143
|
+
expect(mail_message).to receive :deliver_later
|
|
144
|
+
order.finalize!
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "sets confirmation delivered when finalizing" do
|
|
148
|
+
expect(order.confirmation_delivered?).to be false
|
|
149
|
+
order.finalize!
|
|
150
|
+
expect(order.confirmation_delivered?).to be true
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it "should not send duplicate confirmation emails" do
|
|
154
|
+
allow(order).to receive_messages(:confirmation_delivered? => true)
|
|
155
|
+
expect(Spree::OrderMailer).not_to receive(:confirm_email)
|
|
156
|
+
order.finalize!
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "should freeze all adjustments" do
|
|
160
|
+
# Stub this method as it's called due to a callback
|
|
161
|
+
# and it's irrelevant to this test
|
|
162
|
+
allow(order).to receive :has_available_shipment
|
|
163
|
+
allow(Spree::OrderMailer).to receive_message_chain :confirm_email, :deliver_later
|
|
164
|
+
adjustments = [double]
|
|
165
|
+
expect(order).to receive(:all_adjustments).and_return(adjustments)
|
|
166
|
+
adjustments.each do |adj|
|
|
167
|
+
expect(adj).to receive(:close)
|
|
168
|
+
end
|
|
169
|
+
order.finalize!
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
context "order is considered risky" do
|
|
173
|
+
before do
|
|
174
|
+
allow(order).to receive_messages :is_risky? => true
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it "should change state to risky" do
|
|
178
|
+
expect(order).to receive(:considered_risky!)
|
|
179
|
+
order.finalize!
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
context "and order is approved" do
|
|
183
|
+
before do
|
|
184
|
+
allow(order).to receive_messages :approved? => true
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "should leave order in complete state" do
|
|
188
|
+
order.finalize!
|
|
189
|
+
expect(order.state).to eq 'complete'
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
context "insufficient_stock_lines" do
|
|
196
|
+
let(:line_item) { mock_model Spree::LineItem, :insufficient_stock? => true }
|
|
197
|
+
|
|
198
|
+
before { allow(order).to receive_messages(:line_items => [line_item]) }
|
|
199
|
+
|
|
200
|
+
it "should return line_item that has insufficient stock on hand" do
|
|
201
|
+
expect(order.insufficient_stock_lines.size).to eq(1)
|
|
202
|
+
expect(order.insufficient_stock_lines.include?(line_item)).to be true
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
describe '#ensure_line_item_variants_are_not_deleted' do
|
|
207
|
+
subject { order.ensure_line_item_variants_are_not_deleted }
|
|
208
|
+
|
|
209
|
+
let(:order) { create :order_with_line_items }
|
|
210
|
+
|
|
211
|
+
context 'when variant is destroyed' do
|
|
212
|
+
before do
|
|
213
|
+
allow(order).to receive(:restart_checkout_flow)
|
|
214
|
+
order.line_items.first.variant.destroy
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
it 'should restart checkout flow' do
|
|
218
|
+
expect(order).to receive(:restart_checkout_flow).once
|
|
219
|
+
subject
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
it 'should have error message' do
|
|
223
|
+
subject
|
|
224
|
+
expect(order.errors[:base]).to include(Spree.t(:deleted_variants_present))
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it 'should be false' do
|
|
228
|
+
expect(subject).to be_falsey
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context 'when no variants are destroyed' do
|
|
233
|
+
it 'should not restart checkout' do
|
|
234
|
+
expect(order).to receive(:restart_checkout_flow).never
|
|
235
|
+
subject
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it 'should be true' do
|
|
239
|
+
expect(subject).to be_truthy
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
describe '#ensure_line_items_are_in_stock' do
|
|
245
|
+
subject { order.ensure_line_items_are_in_stock }
|
|
246
|
+
|
|
247
|
+
let(:line_item) { mock_model Spree::LineItem, :insufficient_stock? => true }
|
|
248
|
+
|
|
249
|
+
before do
|
|
250
|
+
allow(order).to receive(:restart_checkout_flow)
|
|
251
|
+
allow(order).to receive_messages(:line_items => [line_item])
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
it 'should restart checkout flow' do
|
|
255
|
+
expect(order).to receive(:restart_checkout_flow).once
|
|
256
|
+
subject
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it 'should have error message' do
|
|
260
|
+
subject
|
|
261
|
+
expect(order.errors[:base]).to include(Spree.t(:insufficient_stock_lines_present))
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
it 'should be false' do
|
|
265
|
+
expect(subject).to be_falsey
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
context "empty!" do
|
|
270
|
+
let(:order) { stub_model(Spree::Order, item_count: 2) }
|
|
271
|
+
|
|
272
|
+
before do
|
|
273
|
+
allow(order).to receive_messages(line_items: [1, 2])
|
|
274
|
+
allow(order).to receive_messages(adjustments: [])
|
|
275
|
+
allow(order).to receive_message_chain(:line_items, sum: 0)
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it "clears out line items, adjustments and update totals" do
|
|
279
|
+
expect(order.line_items).to receive(:destroy_all)
|
|
280
|
+
expect(order.adjustments).to receive(:destroy_all)
|
|
281
|
+
expect(order.shipments).to receive(:destroy_all)
|
|
282
|
+
expect(order.updater).to receive(:update_totals)
|
|
283
|
+
expect(order.updater).to receive(:persist_totals)
|
|
284
|
+
|
|
285
|
+
order.empty!
|
|
286
|
+
expect(order.item_total).to eq 0
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
context "#display_outstanding_balance" do
|
|
291
|
+
it "returns the value as a spree money" do
|
|
292
|
+
allow(order).to receive(:outstanding_balance) { 10.55 }
|
|
293
|
+
expect(order.display_outstanding_balance).to eq(Spree::Money.new(10.55))
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
context "#display_item_total" do
|
|
298
|
+
it "returns the value as a spree money" do
|
|
299
|
+
allow(order).to receive(:item_total) { 10.55 }
|
|
300
|
+
expect(order.display_item_total).to eq(Spree::Money.new(10.55))
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
context "#display_adjustment_total" do
|
|
305
|
+
it "returns the value as a spree money" do
|
|
306
|
+
order.adjustment_total = 10.55
|
|
307
|
+
expect(order.display_adjustment_total).to eq(Spree::Money.new(10.55))
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
context "#display_promo_total" do
|
|
312
|
+
it "returns the value as a spree money" do
|
|
313
|
+
order.promo_total = 10.55
|
|
314
|
+
expect(order.display_promo_total).to eq(Spree::Money.new(10.55))
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
context "#display_total" do
|
|
319
|
+
it "returns the value as a spree money" do
|
|
320
|
+
order.total = 10.55
|
|
321
|
+
expect(order.display_total).to eq(Spree::Money.new(10.55))
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
context "#currency" do
|
|
326
|
+
context "when object currency is ABC" do
|
|
327
|
+
before { order.currency = "ABC" }
|
|
328
|
+
|
|
329
|
+
it "returns the currency from the object" do
|
|
330
|
+
expect(order.currency).to eq("ABC")
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
context "when object currency is nil" do
|
|
335
|
+
before { order.currency = nil }
|
|
336
|
+
|
|
337
|
+
it "returns the globally configured currency" do
|
|
338
|
+
expect(order.currency).to eq("USD")
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
context "#confirmation_required?" do
|
|
344
|
+
|
|
345
|
+
# Regression test for #4117
|
|
346
|
+
it "is required if the state is currently 'confirm'" do
|
|
347
|
+
order = Spree::Order.new
|
|
348
|
+
assert !order.confirmation_required?
|
|
349
|
+
order.state = 'confirm'
|
|
350
|
+
assert order.confirmation_required?
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
context 'Spree::Config[:always_include_confirm_step] == true' do
|
|
354
|
+
|
|
355
|
+
before do
|
|
356
|
+
Spree::Config[:always_include_confirm_step] = true
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
it "returns true if payments empty" do
|
|
360
|
+
order = Spree::Order.new
|
|
361
|
+
assert order.confirmation_required?
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
context 'Spree::Config[:always_include_confirm_step] == false' do
|
|
366
|
+
|
|
367
|
+
it "returns false if payments empty and Spree::Config[:always_include_confirm_step] == false" do
|
|
368
|
+
order = Spree::Order.new
|
|
369
|
+
assert !order.confirmation_required?
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it "does not bomb out when an order has an unpersisted payment" do
|
|
373
|
+
order = Spree::Order.new
|
|
374
|
+
order.payments.build
|
|
375
|
+
assert !order.confirmation_required?
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
context "add_update_hook" do
|
|
382
|
+
before do
|
|
383
|
+
Spree::Order.class_eval do
|
|
384
|
+
register_update_hook :add_awesome_sauce
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
after do
|
|
389
|
+
Spree::Order.update_hooks = Set.new
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
it "calls hook during update" do
|
|
393
|
+
order = create(:order)
|
|
394
|
+
expect(order).to receive(:add_awesome_sauce)
|
|
395
|
+
order.update!
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
it "calls hook during finalize" do
|
|
399
|
+
order = create(:order)
|
|
400
|
+
expect(order).to receive(:add_awesome_sauce)
|
|
401
|
+
order.finalize!
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
describe "#tax_address" do
|
|
406
|
+
before { Spree::Config[:tax_using_ship_address] = tax_using_ship_address }
|
|
407
|
+
subject { order.tax_address }
|
|
408
|
+
|
|
409
|
+
context "when tax_using_ship_address is true" do
|
|
410
|
+
let(:tax_using_ship_address) { true }
|
|
411
|
+
|
|
412
|
+
it 'returns ship_address' do
|
|
413
|
+
expect(subject).to eq(order.ship_address)
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
context "when tax_using_ship_address is not true" do
|
|
418
|
+
let(:tax_using_ship_address) { false }
|
|
419
|
+
|
|
420
|
+
it "returns bill_address" do
|
|
421
|
+
expect(subject).to eq(order.bill_address)
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
describe "#restart_checkout_flow" do
|
|
427
|
+
it "updates the state column to the first checkout_steps value" do
|
|
428
|
+
order = create(:order_with_totals, state: "delivery")
|
|
429
|
+
expect(order.checkout_steps).to eql ["address", "delivery", "complete"]
|
|
430
|
+
expect{ order.restart_checkout_flow }.to change{order.state}.from("delivery").to("address")
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
context "without line items" do
|
|
434
|
+
it "updates the state column to cart" do
|
|
435
|
+
order = create(:order, state: "delivery")
|
|
436
|
+
expect{ order.restart_checkout_flow }.to change{order.state}.from("delivery").to("cart")
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
# Regression tests for #4072
|
|
442
|
+
context "#state_changed" do
|
|
443
|
+
let(:order) { FactoryGirl.create(:order) }
|
|
444
|
+
|
|
445
|
+
it "logs state changes" do
|
|
446
|
+
order.update_column(:payment_state, 'balance_due')
|
|
447
|
+
order.payment_state = 'paid'
|
|
448
|
+
expect(order.state_changes).to be_empty
|
|
449
|
+
order.state_changed('payment')
|
|
450
|
+
state_change = order.state_changes.find_by(:name => 'payment')
|
|
451
|
+
expect(state_change.previous_state).to eq('balance_due')
|
|
452
|
+
expect(state_change.next_state).to eq('paid')
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
it "does not do anything if state does not change" do
|
|
456
|
+
order.update_column(:payment_state, 'balance_due')
|
|
457
|
+
expect(order.state_changes).to be_empty
|
|
458
|
+
order.state_changed('payment')
|
|
459
|
+
expect(order.state_changes).to be_empty
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
# Regression test for #4199
|
|
464
|
+
context "#available_payment_methods" do
|
|
465
|
+
it "includes frontend payment methods" do
|
|
466
|
+
payment_method = Spree::PaymentMethod.create!({
|
|
467
|
+
:name => "Fake",
|
|
468
|
+
:active => true,
|
|
469
|
+
:display_on => "front_end",
|
|
470
|
+
})
|
|
471
|
+
expect(order.available_payment_methods).to include(payment_method)
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
it "includes 'both' payment methods" do
|
|
475
|
+
payment_method = Spree::PaymentMethod.create!({
|
|
476
|
+
:name => "Fake",
|
|
477
|
+
:active => true,
|
|
478
|
+
:display_on => "both",
|
|
479
|
+
})
|
|
480
|
+
expect(order.available_payment_methods).to include(payment_method)
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
it "does not include a payment method twice if display_on is blank" do
|
|
484
|
+
payment_method = Spree::PaymentMethod.create!({
|
|
485
|
+
:name => "Fake",
|
|
486
|
+
:active => true,
|
|
487
|
+
:display_on => "both",
|
|
488
|
+
})
|
|
489
|
+
expect(order.available_payment_methods.count).to eq(1)
|
|
490
|
+
expect(order.available_payment_methods).to include(payment_method)
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
context "#apply_free_shipping_promotions" do
|
|
495
|
+
it "calls out to the FreeShipping promotion handler" do
|
|
496
|
+
shipment = double('Shipment')
|
|
497
|
+
allow(order).to receive_messages :shipments => [shipment]
|
|
498
|
+
expect(Spree::PromotionHandler::FreeShipping).to receive(:new).and_return(handler = double)
|
|
499
|
+
expect(handler).to receive(:activate)
|
|
500
|
+
|
|
501
|
+
expect(Spree::Adjustable::AdjustmentsUpdater).to receive(:update).with(shipment)
|
|
502
|
+
|
|
503
|
+
expect(order.updater).to receive(:update_shipment_total)
|
|
504
|
+
expect(order.updater).to receive(:persist_totals)
|
|
505
|
+
order.apply_free_shipping_promotions
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
context "#products" do
|
|
511
|
+
before :each do
|
|
512
|
+
@variant1 = mock_model(Spree::Variant, :product => "product1")
|
|
513
|
+
@variant2 = mock_model(Spree::Variant, :product => "product2")
|
|
514
|
+
@line_items = [mock_model(Spree::LineItem, :product => "product1", :variant => @variant1, :variant_id => @variant1.id, :quantity => 1),
|
|
515
|
+
mock_model(Spree::LineItem, :product => "product2", :variant => @variant2, :variant_id => @variant2.id, :quantity => 2)]
|
|
516
|
+
allow(order).to receive_messages(:line_items => @line_items)
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
it "gets the quantity of a given variant" do
|
|
520
|
+
expect(order.quantity_of(@variant1)).to eq(1)
|
|
521
|
+
|
|
522
|
+
@variant3 = mock_model(Spree::Variant, :product => "product3")
|
|
523
|
+
expect(order.quantity_of(@variant3)).to eq(0)
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
it "can find a line item matching a given variant" do
|
|
527
|
+
expect(order.find_line_item_by_variant(@variant1)).not_to be_nil
|
|
528
|
+
expect(order.find_line_item_by_variant(mock_model(Spree::Variant))).to be_nil
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
context "match line item with options" do
|
|
532
|
+
before do
|
|
533
|
+
Spree::Order.register_line_item_comparison_hook(:foos_match)
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
after do
|
|
537
|
+
# reset to avoid test pollution
|
|
538
|
+
Spree::Order.line_item_comparison_hooks = Set.new
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
it "matches line item when options match" do
|
|
542
|
+
allow(order).to receive(:foos_match).and_return(true)
|
|
543
|
+
expect(order.line_item_options_match(@line_items.first, {foos: {bar: :zoo}})).to be true
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
it "does not match line item without options" do
|
|
547
|
+
allow(order).to receive(:foos_match).and_return(false)
|
|
548
|
+
expect(order.line_item_options_match(@line_items.first, {})).to be false
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
context "#generate_order_number" do
|
|
554
|
+
context "when no configure" do
|
|
555
|
+
let(:default_length) { 9 + 'R'.length }
|
|
556
|
+
subject(:order_number) { order.generate_number }
|
|
557
|
+
its(:class) { should eq String }
|
|
558
|
+
its(:length) { should eq default_length }
|
|
559
|
+
it { should match /^R/ }
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
context "when length option is 5" do
|
|
563
|
+
let(:option_length) { 5 + 'R'.length }
|
|
564
|
+
it "should be option length for order number" do
|
|
565
|
+
expect(order.generate_number(length: 5).length).to eq option_length
|
|
566
|
+
end
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
context "when letters option is true" do
|
|
570
|
+
it "generates order number include letter" do
|
|
571
|
+
expect(order.generate_number(length: 100, letters: true)).to match /[A-Z]/
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
context "when prefix option is 'P'" do
|
|
576
|
+
it "generates order number and it prefix is 'P'" do
|
|
577
|
+
expect(order.generate_number(prefix: 'P')).to match /^P/
|
|
578
|
+
end
|
|
579
|
+
end
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
describe "#associate_user!" do
|
|
583
|
+
let(:user) { FactoryGirl.create(:user_with_addreses) }
|
|
584
|
+
let(:email) { user.email }
|
|
585
|
+
let(:created_by) { user }
|
|
586
|
+
let(:bill_address) { user.bill_address }
|
|
587
|
+
let(:ship_address) { user.ship_address }
|
|
588
|
+
let(:override_email) { true }
|
|
589
|
+
|
|
590
|
+
let(:order) { FactoryGirl.build(:order, order_attributes) }
|
|
591
|
+
|
|
592
|
+
let(:order_attributes) do
|
|
593
|
+
{
|
|
594
|
+
user: nil,
|
|
595
|
+
email: nil,
|
|
596
|
+
created_by: nil,
|
|
597
|
+
bill_address: nil,
|
|
598
|
+
ship_address: nil
|
|
599
|
+
}
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
def assert_expected_order_state
|
|
603
|
+
expect(order.user).to eql(user)
|
|
604
|
+
expect(order.user_id).to eql(user.id)
|
|
605
|
+
|
|
606
|
+
expect(order.email).to eql(email)
|
|
607
|
+
|
|
608
|
+
expect(order.created_by).to eql(created_by)
|
|
609
|
+
expect(order.created_by_id).to eql(created_by.id)
|
|
610
|
+
|
|
611
|
+
expect(order.bill_address).to eql(bill_address)
|
|
612
|
+
expect(order.bill_address_id).to eql(bill_address.id)
|
|
613
|
+
|
|
614
|
+
expect(order.ship_address).to eql(ship_address)
|
|
615
|
+
expect(order.ship_address_id).to eql(ship_address.id)
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
shared_examples_for "#associate_user!" do |persisted = false|
|
|
619
|
+
it "associates a user to an order" do
|
|
620
|
+
order.associate_user!(user, override_email)
|
|
621
|
+
assert_expected_order_state
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
unless persisted
|
|
625
|
+
it "does not persist the order" do
|
|
626
|
+
expect { order.associate_user!(user) }
|
|
627
|
+
.to_not change(order, :persisted?)
|
|
628
|
+
.from(false)
|
|
629
|
+
end
|
|
630
|
+
end
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
context "when email is set" do
|
|
634
|
+
let(:order_attributes) { super().merge(email: 'test@example.com') }
|
|
635
|
+
|
|
636
|
+
context "when email should be overridden" do
|
|
637
|
+
it_should_behave_like "#associate_user!"
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
context "when email should not be overridden" do
|
|
641
|
+
let(:override_email) { false }
|
|
642
|
+
let(:email) { 'test@example.com' }
|
|
643
|
+
|
|
644
|
+
it_should_behave_like "#associate_user!"
|
|
645
|
+
end
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
context "when created_by is set" do
|
|
649
|
+
let(:order_attributes) { super().merge(created_by: created_by) }
|
|
650
|
+
let(:created_by) { create(:user_with_addreses) }
|
|
651
|
+
|
|
652
|
+
it_should_behave_like "#associate_user!"
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
context "when bill_address is set" do
|
|
656
|
+
let(:order_attributes) { super().merge(bill_address: bill_address) }
|
|
657
|
+
let(:bill_address) { FactoryGirl.build(:address) }
|
|
658
|
+
|
|
659
|
+
it_should_behave_like "#associate_user!"
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
context "when ship_address is set" do
|
|
663
|
+
let(:order_attributes) { super().merge(ship_address: ship_address) }
|
|
664
|
+
let(:ship_address) { FactoryGirl.build(:address) }
|
|
665
|
+
|
|
666
|
+
it_should_behave_like "#associate_user!"
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
context "when the user is not persisted" do
|
|
670
|
+
let(:user) { FactoryGirl.build(:user_with_addreses) }
|
|
671
|
+
|
|
672
|
+
it "does not persist the user" do
|
|
673
|
+
expect { order.associate_user!(user) }
|
|
674
|
+
.to_not change(user, :persisted?)
|
|
675
|
+
.from(false)
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
it_should_behave_like "#associate_user!"
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
context "when the order is persisted" do
|
|
682
|
+
let(:order) { FactoryGirl.create(:order, order_attributes) }
|
|
683
|
+
|
|
684
|
+
it "associates a user to a persisted order" do
|
|
685
|
+
order.associate_user!(user)
|
|
686
|
+
order.reload
|
|
687
|
+
assert_expected_order_state
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
it "does not persist other changes to the order" do
|
|
691
|
+
order.state = 'complete'
|
|
692
|
+
order.associate_user!(user)
|
|
693
|
+
order.reload
|
|
694
|
+
expect(order.state).to eql('cart')
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
it "does not change any other orders" do
|
|
698
|
+
other = FactoryGirl.create(:order)
|
|
699
|
+
order.associate_user!(user)
|
|
700
|
+
expect(other.reload.user).to_not eql(user)
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
it "is not affected by scoping" do
|
|
704
|
+
order.class.where.not(id: order).scoping do
|
|
705
|
+
order.associate_user!(user)
|
|
706
|
+
end
|
|
707
|
+
order.reload
|
|
708
|
+
assert_expected_order_state
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
it_should_behave_like "#associate_user!", true
|
|
712
|
+
end
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
context "#can_ship?" do
|
|
716
|
+
let(:order) { Spree::Order.create }
|
|
717
|
+
|
|
718
|
+
it "should be true for order in the 'complete' state" do
|
|
719
|
+
allow(order).to receive_messages(:complete? => true)
|
|
720
|
+
expect(order.can_ship?).to be true
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
it "should be true for order in the 'resumed' state" do
|
|
724
|
+
allow(order).to receive_messages(:resumed? => true)
|
|
725
|
+
expect(order.can_ship?).to be true
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
it "should be true for an order in the 'awaiting return' state" do
|
|
729
|
+
allow(order).to receive_messages(:awaiting_return? => true)
|
|
730
|
+
expect(order.can_ship?).to be true
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
it "should be true for an order in the 'returned' state" do
|
|
734
|
+
allow(order).to receive_messages(:returned? => true)
|
|
735
|
+
expect(order.can_ship?).to be true
|
|
736
|
+
end
|
|
737
|
+
|
|
738
|
+
it "should be false if the order is neither in the 'complete' nor 'resumed' state" do
|
|
739
|
+
allow(order).to receive_messages(:resumed? => false, :complete? => false)
|
|
740
|
+
expect(order.can_ship?).to be false
|
|
741
|
+
end
|
|
742
|
+
end
|
|
743
|
+
|
|
744
|
+
context "#completed?" do
|
|
745
|
+
it "should indicate if order is completed" do
|
|
746
|
+
order.completed_at = nil
|
|
747
|
+
expect(order.completed?).to be false
|
|
748
|
+
|
|
749
|
+
order.completed_at = Time.now
|
|
750
|
+
expect(order.completed?).to be true
|
|
751
|
+
end
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
context "#allow_checkout?" do
|
|
755
|
+
it "should be true if there are line_items in the order" do
|
|
756
|
+
allow(order).to receive_message_chain(:line_items, :count => 1)
|
|
757
|
+
expect(order.checkout_allowed?).to be true
|
|
758
|
+
end
|
|
759
|
+
it "should be false if there are no line_items in the order" do
|
|
760
|
+
allow(order).to receive_message_chain(:line_items, :count => 0)
|
|
761
|
+
expect(order.checkout_allowed?).to be false
|
|
762
|
+
end
|
|
763
|
+
end
|
|
764
|
+
|
|
765
|
+
context "#amount" do
|
|
766
|
+
before do
|
|
767
|
+
@order = create(:order, :user => user)
|
|
768
|
+
@order.line_items = [create(:line_item, :price => 1.0, :quantity => 2),
|
|
769
|
+
create(:line_item, :price => 1.0, :quantity => 1)]
|
|
770
|
+
end
|
|
771
|
+
it "should return the correct lum sum of items" do
|
|
772
|
+
expect(@order.amount).to eq(3.0)
|
|
773
|
+
end
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
context "#backordered?" do
|
|
777
|
+
it 'is backordered if one of the shipments is backordered' do
|
|
778
|
+
allow(order).to receive_messages(:shipments => [mock_model(Spree::Shipment, :backordered? => false),
|
|
779
|
+
mock_model(Spree::Shipment, :backordered? => true)])
|
|
780
|
+
expect(order).to be_backordered
|
|
781
|
+
end
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
context "#can_cancel?" do
|
|
785
|
+
it "should be false for completed order in the canceled state" do
|
|
786
|
+
order.state = 'canceled'
|
|
787
|
+
order.shipment_state = 'ready'
|
|
788
|
+
order.completed_at = Time.now
|
|
789
|
+
expect(order.can_cancel?).to be false
|
|
790
|
+
end
|
|
791
|
+
|
|
792
|
+
it "should be true for completed order with no shipment" do
|
|
793
|
+
order.state = 'complete'
|
|
794
|
+
order.shipment_state = nil
|
|
795
|
+
order.completed_at = Time.now
|
|
796
|
+
expect(order.can_cancel?).to be true
|
|
797
|
+
end
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
context "#tax_total" do
|
|
801
|
+
it "adds included tax and additional tax" do
|
|
802
|
+
allow(order).to receive_messages(:additional_tax_total => 10, :included_tax_total => 20)
|
|
803
|
+
|
|
804
|
+
expect(order.tax_total).to eq 30
|
|
805
|
+
end
|
|
806
|
+
end
|
|
807
|
+
|
|
808
|
+
# Regression test for #4923
|
|
809
|
+
context "locking" do
|
|
810
|
+
let(:order) { Spree::Order.create } # need a persisted in order to test locking
|
|
811
|
+
|
|
812
|
+
it 'can lock' do
|
|
813
|
+
expect { order.with_lock {} }.to_not raise_error
|
|
814
|
+
end
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
describe "#pre_tax_item_amount" do
|
|
818
|
+
it "sums all of the line items' pre tax amounts" do
|
|
819
|
+
subject.line_items = [
|
|
820
|
+
Spree::LineItem.new(price: 10, quantity: 2, pre_tax_amount: 5.0),
|
|
821
|
+
Spree::LineItem.new(price: 30, quantity: 1, pre_tax_amount: 14.0),
|
|
822
|
+
]
|
|
823
|
+
|
|
824
|
+
expect(subject.pre_tax_item_amount).to eq 19.0
|
|
825
|
+
end
|
|
826
|
+
end
|
|
827
|
+
|
|
828
|
+
describe '#quantity' do
|
|
829
|
+
# Uses a persisted record, as the quantity is retrieved via a DB count
|
|
830
|
+
let(:order) { create :order_with_line_items, line_items_count: 3 }
|
|
831
|
+
|
|
832
|
+
it 'sums the quantity of all line items' do
|
|
833
|
+
expect(order.quantity).to eq 3
|
|
834
|
+
end
|
|
835
|
+
end
|
|
836
|
+
|
|
837
|
+
describe '#has_non_reimbursement_related_refunds?' do
|
|
838
|
+
subject do
|
|
839
|
+
order.has_non_reimbursement_related_refunds?
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
context 'no refunds exist' do
|
|
843
|
+
it { is_expected.to eq false }
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
context 'a non-reimbursement related refund exists' do
|
|
847
|
+
let(:order) { refund.payment.order }
|
|
848
|
+
let(:refund) { create(:refund, reimbursement_id: nil, amount: 5) }
|
|
849
|
+
|
|
850
|
+
it { is_expected.to eq true }
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
context 'an old-style refund exists' do
|
|
854
|
+
let(:order) { create(:order_ready_to_ship) }
|
|
855
|
+
let(:payment) { order.payments.first.tap { |p| allow(p).to receive_messages(profiles_supported: false) } }
|
|
856
|
+
let!(:refund_payment) {
|
|
857
|
+
build(:payment, amount: -1, order: order, state: 'completed', source: payment).tap do |p|
|
|
858
|
+
allow(p).to receive_messages(profiles_supported?: false)
|
|
859
|
+
p.save!
|
|
860
|
+
end
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
it { is_expected.to eq true }
|
|
864
|
+
end
|
|
865
|
+
|
|
866
|
+
context 'a reimbursement related refund exists' do
|
|
867
|
+
let(:order) { refund.payment.order }
|
|
868
|
+
let(:refund) { create(:refund, reimbursement_id: 123, amount: 5)}
|
|
869
|
+
|
|
870
|
+
it { is_expected.to eq false }
|
|
871
|
+
end
|
|
872
|
+
end
|
|
873
|
+
|
|
874
|
+
describe "#create_proposed_shipments" do
|
|
875
|
+
it "assigns the coordinator returned shipments to its shipments" do
|
|
876
|
+
shipment = build(:shipment)
|
|
877
|
+
allow_any_instance_of(Spree::Stock::Coordinator).to receive(:shipments).and_return([shipment])
|
|
878
|
+
subject.create_proposed_shipments
|
|
879
|
+
expect(subject.shipments).to eq [shipment]
|
|
880
|
+
end
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
describe "#all_inventory_units_returned?" do
|
|
884
|
+
let(:order) { create(:order_with_line_items, line_items_count: 3) }
|
|
885
|
+
|
|
886
|
+
subject { order.all_inventory_units_returned? }
|
|
887
|
+
|
|
888
|
+
context "all inventory units are returned" do
|
|
889
|
+
before { order.inventory_units.update_all(state: 'returned') }
|
|
890
|
+
|
|
891
|
+
it "is true" do
|
|
892
|
+
expect(subject).to eq true
|
|
893
|
+
end
|
|
894
|
+
end
|
|
895
|
+
|
|
896
|
+
context "some inventory units are returned" do
|
|
897
|
+
before do
|
|
898
|
+
order.inventory_units.first.update_attribute(:state, 'returned')
|
|
899
|
+
end
|
|
900
|
+
|
|
901
|
+
it "is false" do
|
|
902
|
+
expect(subject).to eq false
|
|
903
|
+
end
|
|
904
|
+
end
|
|
905
|
+
|
|
906
|
+
context "no inventory units are returned" do
|
|
907
|
+
it "is false" do
|
|
908
|
+
expect(subject).to eq false
|
|
909
|
+
end
|
|
910
|
+
end
|
|
911
|
+
end
|
|
912
|
+
|
|
913
|
+
describe "#fully_discounted?" do
|
|
914
|
+
let(:line_item) { Spree::LineItem.new(price: 10, quantity: 1) }
|
|
915
|
+
let(:shipment) { Spree::Shipment.new(cost: 10) }
|
|
916
|
+
let(:payment) { Spree::Payment.new(amount: 10) }
|
|
917
|
+
|
|
918
|
+
before do
|
|
919
|
+
allow(order).to receive(:line_items) { [line_item] }
|
|
920
|
+
allow(order).to receive(:shipments) { [shipment] }
|
|
921
|
+
allow(order).to receive(:payments) { [payment] }
|
|
922
|
+
end
|
|
923
|
+
|
|
924
|
+
context "the order had no inventory-related cost" do
|
|
925
|
+
before do
|
|
926
|
+
# discount the cost of the line items
|
|
927
|
+
allow(order).to receive(:adjustment_total) { -5 }
|
|
928
|
+
allow(line_item).to receive(:adjustment_total) { -5 }
|
|
929
|
+
|
|
930
|
+
# but leave some shipment payment amount
|
|
931
|
+
allow(shipment).to receive(:adjustment_total) { 0 }
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
it { expect(order.fully_discounted?).to eq true }
|
|
935
|
+
|
|
936
|
+
end
|
|
937
|
+
|
|
938
|
+
context "the order had inventory-related cost" do
|
|
939
|
+
before do
|
|
940
|
+
# partially discount the cost of the line item
|
|
941
|
+
allow(order).to receive(:adjustment_total) { 0 }
|
|
942
|
+
allow(line_item).to receive(:adjustment_total) { -5 }
|
|
943
|
+
|
|
944
|
+
# and partially discount the cost of the shipment so the total
|
|
945
|
+
# discount matches the item total for test completeness
|
|
946
|
+
allow(shipment).to receive(:adjustment_total) { -5 }
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
it { expect(order.fully_discounted?).to eq false }
|
|
950
|
+
|
|
951
|
+
end
|
|
952
|
+
end
|
|
953
|
+
|
|
954
|
+
end
|