solidus_core 1.0.2 → 1.0.3
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 +1 -0
- data/Gemfile +3 -0
- data/Rakefile +16 -0
- data/script/rails +9 -0
- data/solidus_core.gemspec +48 -0
- data/spec/fixtures/thinking-cat.jpg +0 -0
- data/spec/helpers/base_helper_spec.rb +173 -0
- data/spec/helpers/order_helper_spec.rb +12 -0
- data/spec/helpers/products_helper_spec.rb +220 -0
- data/spec/helpers/taxons_helper_spec.rb +17 -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/search/variant_spec.rb +92 -0
- data/spec/lib/spree/core/controller_helpers/auth_spec.rb +66 -0
- data/spec/lib/spree/core/controller_helpers/order_spec.rb +92 -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/current_store_spec.rb +36 -0
- data/spec/lib/spree/core/delegate_belongs_to_spec.rb +22 -0
- data/spec/lib/spree/core/importer/order_spec.rb +431 -0
- data/spec/lib/spree/core/role_configuration_spec.rb +138 -0
- data/spec/lib/spree/core/validators/email_spec.rb +48 -0
- data/spec/lib/spree/localized_number_spec.rb +38 -0
- data/spec/lib/spree/migrations_spec.rb +36 -0
- data/spec/lib/spree/money_spec.rb +127 -0
- data/spec/lib/tasks/exchanges_spec.rb +231 -0
- data/spec/lib/tasks/migrations/copy_shipped_shipments_to_cartons_spec.rb +115 -0
- data/spec/lib/tasks/order_capturing_spec.rb +56 -0
- data/spec/mailers/carton_mailer_spec.rb +43 -0
- data/spec/mailers/order_mailer_spec.rb +122 -0
- data/spec/mailers/reimbursement_mailer_spec.rb +40 -0
- data/spec/mailers/test_mailer_spec.rb +15 -0
- data/spec/models/spree/ability_spec.rb +276 -0
- data/spec/models/spree/address_spec.rb +250 -0
- data/spec/models/spree/adjustment_reason_spec.rb +13 -0
- data/spec/models/spree/adjustment_spec.rb +177 -0
- data/spec/models/spree/app_configuration_spec.rb +20 -0
- data/spec/models/spree/asset_spec.rb +24 -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/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 +30 -0
- data/spec/models/spree/calculator/tiered_flat_rate_spec.rb +36 -0
- data/spec/models/spree/calculator/tiered_percent_spec.rb +47 -0
- data/spec/models/spree/calculator_spec.rb +36 -0
- data/spec/models/spree/carton_spec.rb +133 -0
- data/spec/models/spree/classification_spec.rb +15 -0
- data/spec/models/spree/concerns/display_money_spec.rb +43 -0
- data/spec/models/spree/concerns/user_methods_spec.rb +41 -0
- data/spec/models/spree/credit_card_spec.rb +334 -0
- data/spec/models/spree/customer_return_spec.rb +276 -0
- data/spec/models/spree/exchange_spec.rb +79 -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 +82 -0
- data/spec/models/spree/inventory_unit_spec.rb +307 -0
- data/spec/models/spree/item_adjustments_spec.rb +256 -0
- data/spec/models/spree/line_item_spec.rb +191 -0
- data/spec/models/spree/option_type_spec.rb +14 -0
- data/spec/models/spree/option_value_spec.rb +22 -0
- data/spec/models/spree/order/address_spec.rb +50 -0
- data/spec/models/spree/order/adjustments_spec.rb +39 -0
- data/spec/models/spree/order/callbacks_spec.rb +42 -0
- data/spec/models/spree/order/checkout_spec.rb +902 -0
- data/spec/models/spree/order/currency_updater_spec.rb +32 -0
- data/spec/models/spree/order/finalizing_spec.rb +111 -0
- data/spec/models/spree/order/payment_spec.rb +210 -0
- data/spec/models/spree/order/risk_assessment_spec.rb +68 -0
- data/spec/models/spree/order/state_machine_spec.rb +221 -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_cancellations_spec.rb +120 -0
- data/spec/models/spree/order_capturing_spec.rb +116 -0
- data/spec/models/spree/order_contents_spec.rb +265 -0
- data/spec/models/spree/order_inventory_spec.rb +228 -0
- data/spec/models/spree/order_mutex_spec.rb +85 -0
- data/spec/models/spree/order_promotion_spec.rb +31 -0
- data/spec/models/spree/order_shipping_spec.rb +247 -0
- data/spec/models/spree/order_spec.rb +1412 -0
- data/spec/models/spree/order_stock_location_spec.rb +18 -0
- data/spec/models/spree/order_updater_spec.rb +299 -0
- data/spec/models/spree/payment_method/store_credit_spec.rb +294 -0
- data/spec/models/spree/payment_method_spec.rb +96 -0
- data/spec/models/spree/payment_spec.rb +1044 -0
- data/spec/models/spree/permission_sets/base_spec.rb +12 -0
- data/spec/models/spree/permission_sets/configuration_display.rb +82 -0
- data/spec/models/spree/permission_sets/configuration_management_spec.rb +50 -0
- data/spec/models/spree/permission_sets/dashboard_display_spec.rb +22 -0
- data/spec/models/spree/permission_sets/order_display_spec.rb +49 -0
- data/spec/models/spree/permission_sets/order_management_spec.rb +36 -0
- data/spec/models/spree/permission_sets/product_display_spec.rb +60 -0
- data/spec/models/spree/permission_sets/product_management_spec.rb +40 -0
- data/spec/models/spree/permission_sets/promotion_display_spec.rb +34 -0
- data/spec/models/spree/permission_sets/promotion_management_spec.rb +26 -0
- data/spec/models/spree/permission_sets/report_display_spec.rb +24 -0
- data/spec/models/spree/permission_sets/restricted_transfer_management_spec.rb +132 -0
- data/spec/models/spree/permission_sets/stock_display_spec.rb +26 -0
- data/spec/models/spree/permission_sets/stock_management_spec.rb +24 -0
- data/spec/models/spree/permission_sets/user_display_spec.rb +36 -0
- data/spec/models/spree/permission_sets/user_management_spec.rb +28 -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 +294 -0
- data/spec/models/spree/preferences/scoped_store_spec.rb +58 -0
- data/spec/models/spree/preferences/static_model_preferences_spec.rb +78 -0
- data/spec/models/spree/preferences/statically_configurable_spec.rb +60 -0
- data/spec/models/spree/preferences/store_spec.rb +39 -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_property_spec.rb +20 -0
- data/spec/models/spree/product_spec.rb +437 -0
- data/spec/models/spree/promotion/actions/create_adjustment_spec.rb +96 -0
- data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +165 -0
- data/spec/models/spree/promotion/actions/create_quantity_adjustments_spec.rb +115 -0
- data/spec/models/spree/promotion/actions/free_shipping_spec.rb +40 -0
- data/spec/models/spree/promotion/rules/first_order_spec.rb +75 -0
- data/spec/models/spree/promotion/rules/item_total_spec.rb +67 -0
- data/spec/models/spree/promotion/rules/nth_order_spec.rb +70 -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 +94 -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_builder_spec.rb +118 -0
- data/spec/models/spree/promotion_category_spec.rb +17 -0
- data/spec/models/spree/promotion_code/code_builder_spec.rb +79 -0
- data/spec/models/spree/promotion_code_spec.rb +187 -0
- data/spec/models/spree/promotion_handler/cart_spec.rb +114 -0
- data/spec/models/spree/promotion_handler/coupon_spec.rb +335 -0
- data/spec/models/spree/promotion_handler/free_shipping_spec.rb +47 -0
- data/spec/models/spree/promotion_handler/page_spec.rb +44 -0
- data/spec/models/spree/promotion_rule_spec.rb +28 -0
- data/spec/models/spree/promotion_spec.rb +767 -0
- data/spec/models/spree/refund_spec.rb +204 -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 +231 -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 +107 -0
- data/spec/models/spree/reimbursement_type/store_credit_spec.rb +97 -0
- data/spec/models/spree/return_authorization_spec.rb +290 -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 +85 -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 +775 -0
- data/spec/models/spree/returns_calculator_spec.rb +14 -0
- data/spec/models/spree/shipment_spec.rb +709 -0
- data/spec/models/spree/shipping_calculator_spec.rb +45 -0
- data/spec/models/spree/shipping_method_spec.rb +88 -0
- data/spec/models/spree/shipping_rate_spec.rb +142 -0
- data/spec/models/spree/state_spec.rb +14 -0
- data/spec/models/spree/stock/availability_validator_spec.rb +83 -0
- data/spec/models/spree/stock/coordinator_spec.rb +116 -0
- data/spec/models/spree/stock/differentiator_spec.rb +39 -0
- data/spec/models/spree/stock/estimator_spec.rb +146 -0
- data/spec/models/spree/stock/inventory_unit_builder_spec.rb +38 -0
- data/spec/models/spree/stock/package_spec.rb +163 -0
- data/spec/models/spree/stock/packer_spec.rb +91 -0
- data/spec/models/spree/stock/prioritizer_spec.rb +125 -0
- data/spec/models/spree/stock/quantifier_spec.rb +115 -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 +50 -0
- data/spec/models/spree/stock/splitter/weight_spec.rb +29 -0
- data/spec/models/spree/stock_item_spec.rb +426 -0
- data/spec/models/spree/stock_location_spec.rb +279 -0
- data/spec/models/spree/stock_movement_spec.rb +56 -0
- data/spec/models/spree/stock_transfer_spec.rb +290 -0
- data/spec/models/spree/store_credit_category_spec.rb +17 -0
- data/spec/models/spree/store_credit_event_spec.rb +314 -0
- data/spec/models/spree/store_credit_spec.rb +876 -0
- data/spec/models/spree/store_spec.rb +55 -0
- data/spec/models/spree/tax_category_spec.rb +27 -0
- data/spec/models/spree/tax_rate_spec.rb +378 -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/transfer_item_spec.rb +264 -0
- data/spec/models/spree/unit_cancel_spec.rb +148 -0
- data/spec/models/spree/user_spec.rb +223 -0
- data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +23 -0
- data/spec/models/spree/variant/scopes_spec.rb +55 -0
- data/spec/models/spree/variant_spec.rb +546 -0
- data/spec/models/spree/zone_spec.rb +305 -0
- data/spec/spec_helper.rb +78 -0
- data/spec/support/big_decimal.rb +5 -0
- data/spec/support/concerns/default_price.rb +34 -0
- data/spec/support/dummy_ability.rb +4 -0
- data/spec/support/test_gateway.rb +2 -0
- metadata +229 -3
- data/lib/spree/testing_support/rspec-activemodel-mocks_patch.rb +0 -8
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Stock
|
|
5
|
+
describe Prioritizer, :type => :model do
|
|
6
|
+
let(:order) { mock_model(Order) }
|
|
7
|
+
let(:stock_location) { build(:stock_location) }
|
|
8
|
+
let(:variant) { build(:variant) }
|
|
9
|
+
|
|
10
|
+
def inventory_units
|
|
11
|
+
@inventory_units ||= []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def build_inventory_unit
|
|
15
|
+
mock_model(InventoryUnit, variant: variant).tap do |unit|
|
|
16
|
+
inventory_units << unit
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def pack
|
|
21
|
+
package = Package.new(order)
|
|
22
|
+
yield(package) if block_given?
|
|
23
|
+
package
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'keeps a single package' do
|
|
27
|
+
package1 = pack do |package|
|
|
28
|
+
package.add build_inventory_unit
|
|
29
|
+
package.add build_inventory_unit
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
packages = [package1]
|
|
33
|
+
prioritizer = Prioritizer.new(inventory_units, packages)
|
|
34
|
+
packages = prioritizer.prioritized_packages
|
|
35
|
+
expect(packages.size).to eq 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'removes duplicate packages' do
|
|
39
|
+
package1 = pack do |package|
|
|
40
|
+
package.add build_inventory_unit
|
|
41
|
+
package.add build_inventory_unit
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
package2 = pack do |package|
|
|
45
|
+
package.add inventory_units.first
|
|
46
|
+
package.add inventory_units.last
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
packages = [package1, package2]
|
|
50
|
+
prioritizer = Prioritizer.new(inventory_units, packages)
|
|
51
|
+
packages = prioritizer.prioritized_packages
|
|
52
|
+
expect(packages.size).to eq 1
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'split over 2 packages' do
|
|
56
|
+
package1 = pack do |package|
|
|
57
|
+
package.add build_inventory_unit
|
|
58
|
+
end
|
|
59
|
+
package2 = pack do |package|
|
|
60
|
+
package.add build_inventory_unit
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
packages = [package1, package2]
|
|
64
|
+
prioritizer = Prioritizer.new(inventory_units, packages)
|
|
65
|
+
packages = prioritizer.prioritized_packages
|
|
66
|
+
expect(packages.size).to eq 2
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it '1st has some, 2nd has remaining' do
|
|
70
|
+
5.times { build_inventory_unit }
|
|
71
|
+
|
|
72
|
+
package1 = pack do |package|
|
|
73
|
+
2.times { |i| package.add inventory_units[i] }
|
|
74
|
+
end
|
|
75
|
+
package2 = pack do |package|
|
|
76
|
+
5.times { |i| package.add inventory_units[i] }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
packages = [package1, package2]
|
|
80
|
+
prioritizer = Prioritizer.new(inventory_units, packages)
|
|
81
|
+
packages = prioritizer.prioritized_packages
|
|
82
|
+
expect(packages.count).to eq 2
|
|
83
|
+
expect(packages[0].quantity).to eq 2
|
|
84
|
+
expect(packages[1].quantity).to eq 3
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it '1st has backorder, 2nd has some' do
|
|
88
|
+
5.times { build_inventory_unit }
|
|
89
|
+
|
|
90
|
+
package1 = pack do |package|
|
|
91
|
+
5.times { |i| package.add inventory_units[i], :backordered }
|
|
92
|
+
end
|
|
93
|
+
package2 = pack do |package|
|
|
94
|
+
2.times { |i| package.add inventory_units[i] }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
packages = [package1, package2]
|
|
98
|
+
prioritizer = Prioritizer.new(inventory_units, packages)
|
|
99
|
+
packages = prioritizer.prioritized_packages
|
|
100
|
+
|
|
101
|
+
expect(packages[0].quantity(:backordered)).to eq 3
|
|
102
|
+
expect(packages[1].quantity(:on_hand)).to eq 2
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it '1st has backorder, 2nd has all' do
|
|
106
|
+
5.times { build_inventory_unit }
|
|
107
|
+
|
|
108
|
+
package1 = pack do |package|
|
|
109
|
+
3.times { |i| package.add inventory_units[i], :backordered }
|
|
110
|
+
end
|
|
111
|
+
package2 = pack do |package|
|
|
112
|
+
5.times { |i| package.add inventory_units[i] }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
packages = [package1, package2]
|
|
116
|
+
prioritizer = Prioritizer.new(inventory_units, packages)
|
|
117
|
+
packages = prioritizer.prioritized_packages
|
|
118
|
+
expect(packages[0]).to eq package2
|
|
119
|
+
expect(packages[1]).to be_nil
|
|
120
|
+
expect(packages[0].quantity(:backordered)).to eq 0
|
|
121
|
+
expect(packages[0].quantity(:on_hand)).to eq 5
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
shared_examples_for 'unlimited supply' do
|
|
4
|
+
it 'can_supply? any amount' do
|
|
5
|
+
expect(subject.can_supply?(1)).to eq true
|
|
6
|
+
expect(subject.can_supply?(101)).to eq true
|
|
7
|
+
expect(subject.can_supply?(100_001)).to eq true
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module Spree
|
|
12
|
+
module Stock
|
|
13
|
+
describe Quantifier, :type => :model do
|
|
14
|
+
|
|
15
|
+
let(:target_stock_location) { nil }
|
|
16
|
+
let!(:stock_location) { create :stock_location_with_items }
|
|
17
|
+
let!(:stock_item) { stock_location.stock_items.order(:id).first }
|
|
18
|
+
|
|
19
|
+
subject { described_class.new(stock_item.variant, target_stock_location) }
|
|
20
|
+
|
|
21
|
+
specify { expect(subject.stock_items).to eq([stock_item]) }
|
|
22
|
+
|
|
23
|
+
context 'with a single stock location/item' do
|
|
24
|
+
it 'total_on_hand should match stock_item' do
|
|
25
|
+
expect(subject.total_on_hand).to eq stock_item.count_on_hand
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'when track_inventory_levels is false' do
|
|
29
|
+
before { configure_spree_preferences { |config| config.track_inventory_levels = false } }
|
|
30
|
+
|
|
31
|
+
specify { expect(subject.total_on_hand).to eq(Float::INFINITY) }
|
|
32
|
+
|
|
33
|
+
it_should_behave_like 'unlimited supply'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'when variant inventory tracking is off' do
|
|
37
|
+
before { stock_item.variant.track_inventory = false }
|
|
38
|
+
|
|
39
|
+
specify { expect(subject.total_on_hand).to eq(Float::INFINITY) }
|
|
40
|
+
|
|
41
|
+
it_should_behave_like 'unlimited supply'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'when stock item allows backordering' do
|
|
45
|
+
specify { expect(subject.backorderable?).to be true }
|
|
46
|
+
|
|
47
|
+
it_should_behave_like 'unlimited supply'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'when stock item prevents backordering' do
|
|
51
|
+
before { stock_item.update_attributes(backorderable: false) }
|
|
52
|
+
|
|
53
|
+
specify { expect(subject.backorderable?).to be false }
|
|
54
|
+
|
|
55
|
+
it 'can_supply? only upto total_on_hand' do
|
|
56
|
+
expect(subject.can_supply?(1)).to be true
|
|
57
|
+
expect(subject.can_supply?(10)).to be true
|
|
58
|
+
expect(subject.can_supply?(11)).to be false
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
context 'with multiple stock locations/items' do
|
|
65
|
+
let!(:stock_location_2) { create :stock_location }
|
|
66
|
+
let!(:stock_location_3) { create :stock_location, active: false }
|
|
67
|
+
|
|
68
|
+
before do
|
|
69
|
+
stock_location_2.stock_items.where(variant_id: stock_item.variant).update_all(count_on_hand: 5, backorderable: false)
|
|
70
|
+
stock_location_3.stock_items.where(variant_id: stock_item.variant).update_all(count_on_hand: 5, backorderable: false)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'total_on_hand should total all active stock_items' do
|
|
74
|
+
expect(subject.total_on_hand).to eq(15)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context 'when any stock item allows backordering' do
|
|
78
|
+
specify { expect(subject.backorderable?).to be true }
|
|
79
|
+
|
|
80
|
+
it_should_behave_like 'unlimited supply'
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'when all stock items prevent backordering' do
|
|
84
|
+
before { stock_item.update_attributes(backorderable: false) }
|
|
85
|
+
|
|
86
|
+
specify { expect(subject.backorderable?).to be false }
|
|
87
|
+
|
|
88
|
+
it 'can_supply? upto total_on_hand' do
|
|
89
|
+
expect(subject.can_supply?(1)).to be true
|
|
90
|
+
expect(subject.can_supply?(15)).to be true
|
|
91
|
+
expect(subject.can_supply?(16)).to be false
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context 'with a specific stock location' do
|
|
98
|
+
let!(:stock_location_2) { create :stock_location }
|
|
99
|
+
let!(:stock_location_3) { create :stock_location, active: false }
|
|
100
|
+
let(:target_stock_location) { stock_location_3 }
|
|
101
|
+
|
|
102
|
+
before do
|
|
103
|
+
Spree::StockItem.update_all(count_on_hand: 0, backorderable: false)
|
|
104
|
+
stock_location_3.stock_items.where(variant_id: stock_item.variant).update_all(count_on_hand: 5, backorderable: false)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'can_supply? only upto total_on_hand' do
|
|
108
|
+
expect(subject.can_supply?(5)).to eq true
|
|
109
|
+
expect(subject.can_supply?(6)).to eq false
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Stock
|
|
5
|
+
module Splitter
|
|
6
|
+
describe Backordered, :type => :model do
|
|
7
|
+
let(:variant) { build(:variant) }
|
|
8
|
+
|
|
9
|
+
let(:packer) { build(:stock_packer) }
|
|
10
|
+
|
|
11
|
+
subject { Backordered.new(packer) }
|
|
12
|
+
|
|
13
|
+
it 'splits packages by status' do
|
|
14
|
+
package = Package.new(packer.stock_location)
|
|
15
|
+
4.times { package.add build(:inventory_unit, variant: variant) }
|
|
16
|
+
5.times { package.add build(:inventory_unit, variant: variant), :backordered }
|
|
17
|
+
|
|
18
|
+
packages = subject.split([package])
|
|
19
|
+
expect(packages.count).to eq 2
|
|
20
|
+
expect(packages.first.quantity).to eq 4
|
|
21
|
+
expect(packages.first.on_hand.count).to eq 4
|
|
22
|
+
expect(packages.first.backordered.count).to eq 0
|
|
23
|
+
|
|
24
|
+
expect(packages[1].contents.count).to eq 5
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Stock
|
|
5
|
+
module Splitter
|
|
6
|
+
describe Base, :type => :model do
|
|
7
|
+
let(:packer) { build(:stock_packer) }
|
|
8
|
+
|
|
9
|
+
it 'continues to splitter chain' do
|
|
10
|
+
splitter1 = Base.new(packer)
|
|
11
|
+
splitter2 = Base.new(packer, splitter1)
|
|
12
|
+
packages = []
|
|
13
|
+
|
|
14
|
+
expect(splitter1).to receive(:split).with(packages)
|
|
15
|
+
splitter2.split(packages)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Stock
|
|
5
|
+
module Splitter
|
|
6
|
+
describe ShippingCategory, :type => :model do
|
|
7
|
+
|
|
8
|
+
let(:order) { create(:order_with_line_items, line_items_count: 1) }
|
|
9
|
+
let(:line_item) { order.line_items.first }
|
|
10
|
+
let(:variant1) { build(:variant) }
|
|
11
|
+
let(:variant2) { build(:variant) }
|
|
12
|
+
let(:shipping_category_1) { create(:shipping_category, name: 'A') }
|
|
13
|
+
let(:shipping_category_2) { create(:shipping_category, name: 'B') }
|
|
14
|
+
|
|
15
|
+
def inventory_unit1
|
|
16
|
+
build(:inventory_unit, variant: variant1, order: order, line_item: line_item).tap do |inventory_unit|
|
|
17
|
+
inventory_unit.variant.product.shipping_category = shipping_category_1
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def inventory_unit2
|
|
22
|
+
build(:inventory_unit, variant: variant2, order: order, line_item: line_item).tap do |inventory_unit|
|
|
23
|
+
inventory_unit.variant.product.shipping_category = shipping_category_2
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
let(:packer) { build(:stock_packer) }
|
|
28
|
+
|
|
29
|
+
subject { ShippingCategory.new(packer) }
|
|
30
|
+
|
|
31
|
+
it 'splits each package by shipping category' do
|
|
32
|
+
package1 = Package.new(packer.stock_location)
|
|
33
|
+
4.times { package1.add inventory_unit1 }
|
|
34
|
+
8.times { package1.add inventory_unit2 }
|
|
35
|
+
|
|
36
|
+
package2 = Package.new(packer.stock_location)
|
|
37
|
+
6.times { package2.add inventory_unit1 }
|
|
38
|
+
9.times { package2.add inventory_unit2, :backordered }
|
|
39
|
+
|
|
40
|
+
packages = subject.split([package1, package2])
|
|
41
|
+
expect(packages[0].quantity).to eq 4
|
|
42
|
+
expect(packages[1].quantity).to eq 8
|
|
43
|
+
expect(packages[2].quantity).to eq 6
|
|
44
|
+
expect(packages[3].quantity).to eq 9
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Stock
|
|
5
|
+
module Splitter
|
|
6
|
+
describe Weight, :type => :model do
|
|
7
|
+
let(:packer) { build(:stock_packer) }
|
|
8
|
+
let(:variant) { build(:base_variant, :weight => 100) }
|
|
9
|
+
|
|
10
|
+
subject { Weight.new(packer) }
|
|
11
|
+
|
|
12
|
+
it 'splits and keeps splitting until all packages are underweight' do
|
|
13
|
+
package = Package.new(packer.stock_location)
|
|
14
|
+
4.times { package.add build(:inventory_unit, variant: variant) }
|
|
15
|
+
packages = subject.split([package])
|
|
16
|
+
expect(packages.size).to eq 4
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'handles packages that can not be reduced' do
|
|
20
|
+
package = Package.new(packer.stock_location)
|
|
21
|
+
allow(variant).to receive_messages(:weight => 200)
|
|
22
|
+
2.times { package.add build(:inventory_unit, variant: variant) }
|
|
23
|
+
packages = subject.split([package])
|
|
24
|
+
expect(packages.size).to eq 2
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::StockItem, :type => :model do
|
|
4
|
+
let(:stock_location) { create(:stock_location_with_items) }
|
|
5
|
+
|
|
6
|
+
subject { stock_location.stock_items.order(:id).first }
|
|
7
|
+
|
|
8
|
+
it 'maintains the count on hand for a variant' do
|
|
9
|
+
expect(subject.count_on_hand).to eq 10
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "can return the stock item's variant's name" do
|
|
13
|
+
expect(subject.variant_name).to eq(subject.variant.name)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "available to be included in shipment" do
|
|
17
|
+
context "has stock" do
|
|
18
|
+
it { expect(subject).to be_available }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context "backorderable" do
|
|
22
|
+
before { subject.backorderable = true }
|
|
23
|
+
it { expect(subject).to be_available }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context "no stock and not backorderable" do
|
|
27
|
+
before do
|
|
28
|
+
subject.backorderable = false
|
|
29
|
+
allow(subject).to receive_messages(count_on_hand: 0)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it { expect(subject).not_to be_available }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe 'reduce_count_on_hand_to_zero' do
|
|
37
|
+
context 'when count_on_hand > 0' do
|
|
38
|
+
before(:each) do
|
|
39
|
+
subject.update_column('count_on_hand', 4)
|
|
40
|
+
subject.reduce_count_on_hand_to_zero
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it { expect(subject.count_on_hand).to eq(0) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'when count_on_hand > 0' do
|
|
47
|
+
before(:each) do
|
|
48
|
+
subject.update_column('count_on_hand', -4)
|
|
49
|
+
@count_on_hand = subject.count_on_hand
|
|
50
|
+
subject.reduce_count_on_hand_to_zero
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it { expect(subject.count_on_hand).to eq(@count_on_hand) }
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "adjust count_on_hand" do
|
|
58
|
+
let!(:current_on_hand) { subject.count_on_hand }
|
|
59
|
+
|
|
60
|
+
it 'is updated pessimistically' do
|
|
61
|
+
copy = Spree::StockItem.find(subject.id)
|
|
62
|
+
|
|
63
|
+
subject.adjust_count_on_hand(5)
|
|
64
|
+
expect(subject.count_on_hand).to eq(current_on_hand + 5)
|
|
65
|
+
|
|
66
|
+
expect(copy.count_on_hand).to eq(current_on_hand)
|
|
67
|
+
copy.adjust_count_on_hand(5)
|
|
68
|
+
expect(copy.count_on_hand).to eq(current_on_hand + 10)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context "item out of stock (by two items)" do
|
|
72
|
+
let(:inventory_unit) { double('InventoryUnit') }
|
|
73
|
+
let(:inventory_unit_2) { double('InventoryUnit2') }
|
|
74
|
+
|
|
75
|
+
before do
|
|
76
|
+
allow(subject).to receive_messages(:backordered_inventory_units => [inventory_unit, inventory_unit_2])
|
|
77
|
+
subject.update_column(:count_on_hand, -2)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Regression test for #3755
|
|
81
|
+
it "processes existing backorders, even with negative stock" do
|
|
82
|
+
expect(inventory_unit).to receive(:fill_backorder)
|
|
83
|
+
expect(inventory_unit_2).not_to receive(:fill_backorder)
|
|
84
|
+
subject.adjust_count_on_hand(1)
|
|
85
|
+
expect(subject.count_on_hand).to eq(-1)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Test for #3755
|
|
89
|
+
it "does not process backorders when stock is adjusted negatively" do
|
|
90
|
+
expect(inventory_unit).not_to receive(:fill_backorder)
|
|
91
|
+
expect(inventory_unit_2).not_to receive(:fill_backorder)
|
|
92
|
+
subject.adjust_count_on_hand(-1)
|
|
93
|
+
expect(subject.count_on_hand).to eq(-3)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context "adds new items" do
|
|
97
|
+
before { allow(subject).to receive_messages(:backordered_inventory_units => [inventory_unit, inventory_unit_2]) }
|
|
98
|
+
|
|
99
|
+
it "fills existing backorders" do
|
|
100
|
+
expect(inventory_unit).to receive(:fill_backorder)
|
|
101
|
+
expect(inventory_unit_2).to receive(:fill_backorder)
|
|
102
|
+
|
|
103
|
+
subject.adjust_count_on_hand(3)
|
|
104
|
+
expect(subject.count_on_hand).to eq(1)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
context "set count_on_hand" do
|
|
111
|
+
let!(:current_on_hand) { subject.count_on_hand }
|
|
112
|
+
|
|
113
|
+
it 'is updated pessimistically' do
|
|
114
|
+
copy = Spree::StockItem.find(subject.id)
|
|
115
|
+
|
|
116
|
+
subject.set_count_on_hand(5)
|
|
117
|
+
expect(subject.count_on_hand).to eq(5)
|
|
118
|
+
|
|
119
|
+
expect(copy.count_on_hand).to eq(current_on_hand)
|
|
120
|
+
copy.set_count_on_hand(10)
|
|
121
|
+
expect(copy.count_on_hand).to eq(current_on_hand)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context "item out of stock (by two items)" do
|
|
125
|
+
let(:inventory_unit) { double('InventoryUnit') }
|
|
126
|
+
let(:inventory_unit_2) { double('InventoryUnit2') }
|
|
127
|
+
|
|
128
|
+
before { subject.set_count_on_hand(-2) }
|
|
129
|
+
|
|
130
|
+
it "doesn't process backorders" do
|
|
131
|
+
expect(subject).not_to receive(:backordered_inventory_units)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context "adds new items" do
|
|
135
|
+
before { allow(subject).to receive_messages(:backordered_inventory_units => [inventory_unit, inventory_unit_2]) }
|
|
136
|
+
|
|
137
|
+
it "fills existing backorders" do
|
|
138
|
+
expect(inventory_unit).to receive(:fill_backorder)
|
|
139
|
+
expect(inventory_unit_2).to receive(:fill_backorder)
|
|
140
|
+
|
|
141
|
+
subject.set_count_on_hand(1)
|
|
142
|
+
expect(subject.count_on_hand).to eq(1)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
context "with stock movements" do
|
|
149
|
+
before { Spree::StockMovement.create(stock_item: subject, quantity: 1) }
|
|
150
|
+
|
|
151
|
+
it "doesnt raise ReadOnlyRecord error" do
|
|
152
|
+
expect { subject.destroy }.not_to raise_error
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
context "destroyed" do
|
|
157
|
+
before { subject.destroy }
|
|
158
|
+
|
|
159
|
+
it "recreates stock item just fine" do
|
|
160
|
+
expect {
|
|
161
|
+
stock_location.stock_items.create!(variant: subject.variant)
|
|
162
|
+
}.not_to raise_error
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "doesnt allow recreating more than one stock item at once" do
|
|
166
|
+
stock_location.stock_items.create!(variant: subject.variant)
|
|
167
|
+
|
|
168
|
+
expect {
|
|
169
|
+
stock_location.stock_items.create!(variant: subject.variant)
|
|
170
|
+
}.to raise_error ActiveRecord::RecordInvalid
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
describe "#after_save" do
|
|
175
|
+
before do
|
|
176
|
+
subject.variant.update_column(:updated_at, 1.day.ago)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
before do
|
|
180
|
+
Spree::Config.binary_inventory_cache = binary_inventory_cache
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
context "binary_inventory_cache is set to false (default)" do
|
|
184
|
+
let(:binary_inventory_cache) { false }
|
|
185
|
+
|
|
186
|
+
context "in_stock? changes" do
|
|
187
|
+
it "touches its variant" do
|
|
188
|
+
expect do
|
|
189
|
+
subject.set_count_on_hand(0)
|
|
190
|
+
end.to change { subject.variant.updated_at }
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
context "in_stock? does not change" do
|
|
195
|
+
it "touches its variant" do
|
|
196
|
+
expect do
|
|
197
|
+
subject.set_count_on_hand(-1)
|
|
198
|
+
end.to change { subject.variant.updated_at }
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
context "binary_inventory_cache is set to true" do
|
|
204
|
+
let(:binary_inventory_cache) { true }
|
|
205
|
+
|
|
206
|
+
context "in_stock? changes" do
|
|
207
|
+
it "touches its variant" do
|
|
208
|
+
expect do
|
|
209
|
+
subject.set_count_on_hand(0)
|
|
210
|
+
end.to change { subject.variant.updated_at }
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Regression spec
|
|
214
|
+
context "stock changes to below zero" do
|
|
215
|
+
it "touches its variant" do
|
|
216
|
+
expect do
|
|
217
|
+
subject.set_count_on_hand(-1)
|
|
218
|
+
end.to change { subject.variant.updated_at }
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
context "in_stock? does not change" do
|
|
224
|
+
it "does not touch its variant" do
|
|
225
|
+
expect do
|
|
226
|
+
subject.set_count_on_hand(1)
|
|
227
|
+
end.not_to change { subject.reload.variant.updated_at }
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
context "when a new stock location is added" do
|
|
232
|
+
it "touches its variant" do
|
|
233
|
+
expect do
|
|
234
|
+
create(:stock_location)
|
|
235
|
+
end.to change { subject.variant.reload.updated_at }
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
describe "#after_touch" do
|
|
242
|
+
it "touches its variant" do
|
|
243
|
+
expect do
|
|
244
|
+
subject.touch
|
|
245
|
+
end.to change { subject.variant.updated_at }
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# Regression test for #4651
|
|
250
|
+
context "variant" do
|
|
251
|
+
it "can be found even if the variant is deleted" do
|
|
252
|
+
subject.variant.destroy
|
|
253
|
+
expect(subject.reload.variant).not_to be_nil
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
describe 'validations' do
|
|
258
|
+
describe 'count_on_hand' do
|
|
259
|
+
shared_examples_for 'valid count_on_hand' do
|
|
260
|
+
before(:each) do
|
|
261
|
+
subject.save
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
it 'has :no errors_on' do
|
|
265
|
+
expect(subject.errors_on(:count_on_hand).size).to eq(0)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
shared_examples_for 'not valid count_on_hand' do
|
|
270
|
+
before(:each) do
|
|
271
|
+
subject.save
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it 'has 1 error_on' do
|
|
275
|
+
expect(subject.error_on(:count_on_hand).size).to eq(1)
|
|
276
|
+
end
|
|
277
|
+
it { expect(subject.errors[:count_on_hand]).to include 'must be greater than or equal to 0' }
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
context 'when count_on_hand not changed' do
|
|
281
|
+
context 'when not backorderable' do
|
|
282
|
+
before(:each) do
|
|
283
|
+
subject.backorderable = false
|
|
284
|
+
end
|
|
285
|
+
it_should_behave_like 'valid count_on_hand'
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
context 'when backorderable' do
|
|
289
|
+
before(:each) do
|
|
290
|
+
subject.backorderable = true
|
|
291
|
+
end
|
|
292
|
+
it_should_behave_like 'valid count_on_hand'
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
context 'when count_on_hand changed' do
|
|
297
|
+
context 'when backorderable' do
|
|
298
|
+
before(:each) do
|
|
299
|
+
subject.backorderable = true
|
|
300
|
+
end
|
|
301
|
+
context 'when both count_on_hand and count_on_hand_was are positive' do
|
|
302
|
+
context 'when count_on_hand is greater than count_on_hand_was' do
|
|
303
|
+
before(:each) do
|
|
304
|
+
subject.update_column(:count_on_hand, 3)
|
|
305
|
+
subject.send(:count_on_hand=, subject.count_on_hand + 3)
|
|
306
|
+
end
|
|
307
|
+
it_should_behave_like 'valid count_on_hand'
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
context 'when count_on_hand is smaller than count_on_hand_was' do
|
|
311
|
+
before(:each) do
|
|
312
|
+
subject.update_column(:count_on_hand, 3)
|
|
313
|
+
subject.send(:count_on_hand=, subject.count_on_hand - 2)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
it_should_behave_like 'valid count_on_hand'
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
context 'when both count_on_hand and count_on_hand_was are negative' do
|
|
321
|
+
context 'when count_on_hand is greater than count_on_hand_was' do
|
|
322
|
+
before(:each) do
|
|
323
|
+
subject.update_column(:count_on_hand, -3)
|
|
324
|
+
subject.send(:count_on_hand=, subject.count_on_hand + 2)
|
|
325
|
+
end
|
|
326
|
+
it_should_behave_like 'valid count_on_hand'
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
context 'when count_on_hand is smaller than count_on_hand_was' do
|
|
330
|
+
before(:each) do
|
|
331
|
+
subject.update_column(:count_on_hand, 3)
|
|
332
|
+
subject.send(:count_on_hand=, subject.count_on_hand - 3)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
it_should_behave_like 'valid count_on_hand'
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
context 'when both count_on_hand is positive and count_on_hand_was is negative' do
|
|
340
|
+
context 'when count_on_hand is greater than count_on_hand_was' do
|
|
341
|
+
before(:each) do
|
|
342
|
+
subject.update_column(:count_on_hand, -3)
|
|
343
|
+
subject.send(:count_on_hand=, subject.count_on_hand + 6)
|
|
344
|
+
end
|
|
345
|
+
it_should_behave_like 'valid count_on_hand'
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
context 'when both count_on_hand is negative and count_on_hand_was is positive' do
|
|
350
|
+
context 'when count_on_hand is greater than count_on_hand_was' do
|
|
351
|
+
before(:each) do
|
|
352
|
+
subject.update_column(:count_on_hand, 3)
|
|
353
|
+
subject.send(:count_on_hand=, subject.count_on_hand - 6)
|
|
354
|
+
end
|
|
355
|
+
it_should_behave_like 'valid count_on_hand'
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
context 'when not backorderable' do
|
|
361
|
+
before(:each) do
|
|
362
|
+
subject.backorderable = false
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
context 'when both count_on_hand and count_on_hand_was are positive' do
|
|
366
|
+
context 'when count_on_hand is greater than count_on_hand_was' do
|
|
367
|
+
before(:each) do
|
|
368
|
+
subject.update_column(:count_on_hand, 3)
|
|
369
|
+
subject.send(:count_on_hand=, subject.count_on_hand + 3)
|
|
370
|
+
end
|
|
371
|
+
it_should_behave_like 'valid count_on_hand'
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
context 'when count_on_hand is smaller than count_on_hand_was' do
|
|
375
|
+
before(:each) do
|
|
376
|
+
subject.update_column(:count_on_hand, 3)
|
|
377
|
+
subject.send(:count_on_hand=, subject.count_on_hand - 2)
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
it_should_behave_like 'valid count_on_hand'
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
context 'when both count_on_hand and count_on_hand_was are negative' do
|
|
385
|
+
context 'when count_on_hand is greater than count_on_hand_was' do
|
|
386
|
+
before(:each) do
|
|
387
|
+
subject.update_column(:count_on_hand, -3)
|
|
388
|
+
subject.send(:count_on_hand=, subject.count_on_hand + 2)
|
|
389
|
+
end
|
|
390
|
+
it_should_behave_like 'valid count_on_hand'
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
context 'when count_on_hand is smaller than count_on_hand_was' do
|
|
394
|
+
before(:each) do
|
|
395
|
+
subject.update_column(:count_on_hand, -3)
|
|
396
|
+
subject.send(:count_on_hand=, subject.count_on_hand - 3)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
it_should_behave_like 'not valid count_on_hand'
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
context 'when both count_on_hand is positive and count_on_hand_was is negative' do
|
|
404
|
+
context 'when count_on_hand is greater than count_on_hand_was' do
|
|
405
|
+
before(:each) do
|
|
406
|
+
subject.update_column(:count_on_hand, -3)
|
|
407
|
+
subject.send(:count_on_hand=, subject.count_on_hand + 6)
|
|
408
|
+
end
|
|
409
|
+
it_should_behave_like 'valid count_on_hand'
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
context 'when both count_on_hand is negative and count_on_hand_was is positive' do
|
|
414
|
+
context 'when count_on_hand is greater than count_on_hand_was' do
|
|
415
|
+
before(:each) do
|
|
416
|
+
subject.update_column(:count_on_hand, 3)
|
|
417
|
+
subject.send(:count_on_hand=, subject.count_on_hand - 6)
|
|
418
|
+
end
|
|
419
|
+
it_should_behave_like 'not valid count_on_hand'
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
end
|