solidus_product_assembly 1.0.0
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 +7 -0
- data/.gitignore +4 -0
- data/.rspec +3 -0
- data/.travis.yml +21 -0
- data/Gemfile +18 -0
- data/LICENSE.md +13 -0
- data/README.md +80 -0
- data/Rakefile +21 -0
- data/app/assets/images/spinner.gif +0 -0
- data/app/assets/javascripts/spree/backend/solidus_product_assembly.js +1 -0
- data/app/assets/javascripts/spree/frontend/solidus_product_assembly.js +1 -0
- data/app/assets/stylesheets/spree/backend/solidus_product_assembly.css +3 -0
- data/app/assets/stylesheets/spree/frontend/solidus_product_assembly.css +3 -0
- data/app/controllers/spree/admin/parts_controller.rb +49 -0
- data/app/controllers/spree/checkout_controller_decorator.rb +9 -0
- data/app/helpers/spree/admin/orders_helper_decorator.rb +9 -0
- data/app/models/spree/assemblies_part.rb +12 -0
- data/app/models/spree/inventory_unit_decorator.rb +13 -0
- data/app/models/spree/line_item_decorator.rb +44 -0
- data/app/models/spree/order_inventory_assembly.rb +39 -0
- data/app/models/spree/product_decorator.rb +56 -0
- data/app/models/spree/shipment_decorator.rb +50 -0
- data/app/models/spree/stock/availability_validator.rb +28 -0
- data/app/models/spree/stock/inventory_unit_builder_decorator.rb +30 -0
- data/app/models/spree/stock/inventory_validator_decorator.rb +12 -0
- data/app/models/spree/variant_decorator.rb +13 -0
- data/app/overrides/add_admin_product_form_fields.rb +5 -0
- data/app/overrides/add_admin_tabs.rb +5 -0
- data/app/overrides/add_line_item_description.rb +5 -0
- data/app/overrides/spree/admin/orders/_form/inject_product_assemblies.html.erb.deface +3 -0
- data/app/overrides/spree/admin/orders/_shipment/stock_contents.html.erb.deface +2 -0
- data/app/overrides/spree/checkout/_delivery/remove_unshippable_markup.html.erb.deface +1 -0
- data/app/overrides/spree/checkout/_delivery/render_line_item_manifest.html.erb.deface +3 -0
- data/app/overrides/spree/products/show/add_links_to_parts.html.erb.deface +21 -0
- data/app/overrides/spree/products/show/remove_add_to_cart_button_for_non_individual_sale_products.html.erb.deface +4 -0
- data/app/overrides/spree/shared/_order_details/part_description.html.erb.deface +8 -0
- data/app/views/spree/admin/orders/_assemblies.html.erb +56 -0
- data/app/views/spree/admin/orders/_stock_contents.html.erb +69 -0
- data/app/views/spree/admin/orders/_stock_item.html.erb +46 -0
- data/app/views/spree/admin/parts/_parts_table.html.erb +33 -0
- data/app/views/spree/admin/parts/available.html.erb +55 -0
- data/app/views/spree/admin/parts/available.js.erb +54 -0
- data/app/views/spree/admin/parts/index.html.erb +70 -0
- data/app/views/spree/admin/parts/update_parts_table.js.erb +2 -0
- data/app/views/spree/admin/products/_product_assembly_fields.html.erb +23 -0
- data/app/views/spree/admin/shared/_product_assembly_product_tabs.html.erb +3 -0
- data/app/views/spree/checkout/_line_item_manifest.html.erb +17 -0
- data/app/views/spree/orders/_cart_description.html.erb +8 -0
- data/bin/rails +7 -0
- data/config/locales/en.yml +14 -0
- data/config/locales/fr.yml +12 -0
- data/config/locales/ru.yml +12 -0
- data/config/locales/sv.yml +12 -0
- data/config/routes.rb +19 -0
- data/db/migrate/20091028152124_add_many_to_many_relation_to_products.rb +13 -0
- data/db/migrate/20091029165620_add_parts_fields_to_products.rb +27 -0
- data/db/migrate/20120316141830_namespace_product_assembly_for_spree_one.rb +9 -0
- data/db/migrate/20140620223938_add_id_to_spree_assemblies_parts.rb +9 -0
- data/lib/generators/solidus_product_assembly/install/install_generator.rb +24 -0
- data/lib/solidus_product_assembly.rb +3 -0
- data/lib/solidus_product_assembly/engine.rb +15 -0
- data/lib/solidus_product_assembly/version.rb +3 -0
- data/lib/tasks/spree2_upgrade.rake +29 -0
- data/solidus_product_assembly.gemspec +35 -0
- data/spec/features/admin/orders_spec.rb +29 -0
- data/spec/features/admin/parts_spec.rb +28 -0
- data/spec/features/checkout_spec.rb +92 -0
- data/spec/models/spree/assemblies_part_spec.rb +18 -0
- data/spec/models/spree/inventory_unit_spec.rb +32 -0
- data/spec/models/spree/line_item_spec.rb +72 -0
- data/spec/models/spree/order_contents_spec.rb +40 -0
- data/spec/models/spree/order_inventory_assembly_spec.rb +55 -0
- data/spec/models/spree/order_inventory_spec.rb +35 -0
- data/spec/models/spree/product_spec.rb +35 -0
- data/spec/models/spree/shipment_spec.rb +112 -0
- data/spec/models/spree/stock/availability_validator_spec.rb +71 -0
- data/spec/models/spree/stock/coordinator_spec.rb +52 -0
- data/spec/models/spree/stock/inventory_unit_builder_spec.rb +36 -0
- data/spec/models/spree/variant_spec.rb +28 -0
- data/spec/spec_helper.rb +57 -0
- data/spec/support/shared_contexts/order_with_bundle.rb +13 -0
- metadata +272 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Checkout", type: :feature do
|
4
|
+
let!(:store) { create :store, default: true }
|
5
|
+
let!(:country) { create(:country, :name => "United States", :states_required => true) }
|
6
|
+
let!(:state) { create(:state, :name => "Ohio", :country => country) }
|
7
|
+
let!(:shipping_method) { create(:shipping_method) }
|
8
|
+
let!(:stock_location) { create(:stock_location) }
|
9
|
+
let!(:payment_method) { create(:check_payment_method) }
|
10
|
+
let!(:zone) { create(:zone) }
|
11
|
+
|
12
|
+
let(:product) { create(:product, :name => "RoR Mug") }
|
13
|
+
let(:variant) { create(:variant) }
|
14
|
+
|
15
|
+
stub_authorization!
|
16
|
+
|
17
|
+
before { product.parts << variant << create(:variant) }
|
18
|
+
|
19
|
+
shared_context "purchases product with part included" do
|
20
|
+
before do
|
21
|
+
add_product_to_cart
|
22
|
+
click_button "Checkout"
|
23
|
+
|
24
|
+
fill_in "order_email", :with => "ryan@spreecommerce.com"
|
25
|
+
click_button "Continue"
|
26
|
+
fill_in_address
|
27
|
+
|
28
|
+
click_button "Save and Continue"
|
29
|
+
expect(current_path).to eql(spree.checkout_state_path("delivery"))
|
30
|
+
page.should have_content(variant.product.name)
|
31
|
+
|
32
|
+
click_button "Save and Continue"
|
33
|
+
expect(current_path).to eql(spree.checkout_state_path("payment"))
|
34
|
+
|
35
|
+
click_button "Save and Continue"
|
36
|
+
expect(current_path).to eq spree.checkout_state_path('confirm')
|
37
|
+
page.should have_content(variant.product.name)
|
38
|
+
|
39
|
+
click_button "Place Order"
|
40
|
+
page.should have_content('Your order has been processed successfully')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "backend order shipments UI", js: true do
|
45
|
+
|
46
|
+
context "ordering only the product assembly" do
|
47
|
+
include_context "purchases product with part included"
|
48
|
+
|
49
|
+
it "views parts bundled as well" do
|
50
|
+
visit spree.admin_orders_path
|
51
|
+
click_on Spree::Order.last.number
|
52
|
+
|
53
|
+
page.should have_content(variant.product.name)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "ordering assembly and the part as individual sale" do
|
58
|
+
before do
|
59
|
+
visit spree.root_path
|
60
|
+
click_link variant.product.name
|
61
|
+
click_button "add-to-cart-button"
|
62
|
+
end
|
63
|
+
include_context "purchases product with part included"
|
64
|
+
|
65
|
+
it "views parts bundled and not" do
|
66
|
+
visit spree.admin_orders_path
|
67
|
+
click_on Spree::Order.last.number
|
68
|
+
|
69
|
+
page.should have_content(variant.product.name)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
def fill_in_address
|
77
|
+
address = "order_bill_address_attributes"
|
78
|
+
fill_in "#{address}_firstname", :with => "Ryan"
|
79
|
+
fill_in "#{address}_lastname", :with => "Bigg"
|
80
|
+
fill_in "#{address}_address1", :with => "143 Swan Street"
|
81
|
+
fill_in "#{address}_city", :with => "Richmond"
|
82
|
+
select "Ohio", :from => "#{address}_state_id"
|
83
|
+
fill_in "#{address}_zipcode", :with => "12345"
|
84
|
+
fill_in "#{address}_phone", :with => "(555) 555-5555"
|
85
|
+
end
|
86
|
+
|
87
|
+
def add_product_to_cart
|
88
|
+
visit spree.root_path
|
89
|
+
click_link product.name
|
90
|
+
click_button "add-to-cart-button"
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
describe AssembliesPart do
|
5
|
+
let(:product) { create(:product) }
|
6
|
+
let(:variant) { create(:variant) }
|
7
|
+
|
8
|
+
before do
|
9
|
+
product.parts.push variant
|
10
|
+
end
|
11
|
+
|
12
|
+
context "get" do
|
13
|
+
it "brings part by product and variant id" do
|
14
|
+
subject.class.get(product.id, variant.id).part.should == variant
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
describe InventoryUnit do
|
5
|
+
let!(:order) { create(:order_with_line_items) }
|
6
|
+
let(:line_item) { order.line_items.first }
|
7
|
+
let(:product) { line_item.product }
|
8
|
+
|
9
|
+
subject { InventoryUnit.create(line_item: line_item, variant: line_item.variant, order: order) }
|
10
|
+
|
11
|
+
context 'if the unit is not part of an assembly' do
|
12
|
+
it 'it will return the percentage of a line item' do
|
13
|
+
expect(subject.percentage_of_line_item).to eql(BigDecimal.new(1))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'if part of an assembly' do
|
18
|
+
let(:parts) { (1..2).map { create(:variant) } }
|
19
|
+
|
20
|
+
before do
|
21
|
+
product.parts << parts
|
22
|
+
order.create_proposed_shipments
|
23
|
+
order.finalize!
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'it will return the percentage of a line item' do
|
27
|
+
subject.line_item = line_item
|
28
|
+
expect(subject.percentage_of_line_item).to eql(BigDecimal.new(0.5, 2))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
describe LineItem do
|
5
|
+
let!(:order) { create(:order_with_line_items) }
|
6
|
+
let(:line_item) { order.line_items.first }
|
7
|
+
let(:product) { line_item.product }
|
8
|
+
let(:variant) { line_item.variant }
|
9
|
+
let(:inventory) { double('order_inventory') }
|
10
|
+
|
11
|
+
context "bundle parts stock" do
|
12
|
+
let(:parts) { (1..2).map { create(:variant) } }
|
13
|
+
|
14
|
+
before { product.parts << parts }
|
15
|
+
|
16
|
+
context "one of them not in stock" do
|
17
|
+
before do
|
18
|
+
part = product.parts.first
|
19
|
+
part.stock_items.update_all backorderable: false
|
20
|
+
|
21
|
+
expect(part).not_to be_in_stock
|
22
|
+
end
|
23
|
+
|
24
|
+
it "doesn't save line item quantity" do
|
25
|
+
order.contents.add(variant, 10)
|
26
|
+
expect { order.contents.advance }.to raise_error Spree::Order::InsufficientStock
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "in stock" do
|
31
|
+
before do
|
32
|
+
parts.each do |part|
|
33
|
+
part.stock_items.first.set_count_on_hand(10)
|
34
|
+
end
|
35
|
+
expect(parts[0]).to be_in_stock
|
36
|
+
expect(parts[1]).to be_in_stock
|
37
|
+
end
|
38
|
+
|
39
|
+
it "saves line item quantity" do
|
40
|
+
line_item = order.contents.add(variant, 10)
|
41
|
+
expect(line_item).to be_valid
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "updates bundle product line item" do
|
47
|
+
let(:parts) { (1..2).map { create(:variant) } }
|
48
|
+
|
49
|
+
before do
|
50
|
+
product.parts << parts
|
51
|
+
order.create_proposed_shipments
|
52
|
+
order.finalize!
|
53
|
+
end
|
54
|
+
|
55
|
+
it "verifies inventory units via OrderInventoryAssembly" do
|
56
|
+
OrderInventoryAssembly.should_receive(:new).with(line_item).and_return(inventory)
|
57
|
+
inventory.should_receive(:verify).with(line_item.target_shipment)
|
58
|
+
line_item.quantity = 2
|
59
|
+
line_item.save
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "updates regular line item" do
|
64
|
+
it "verifies inventory units via OrderInventory" do
|
65
|
+
OrderInventory.should_receive(:new).with(line_item.order, line_item).and_return(inventory)
|
66
|
+
inventory.should_receive(:verify).with(line_item.target_shipment)
|
67
|
+
line_item.quantity = 2
|
68
|
+
line_item.save
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
describe OrderContents do
|
5
|
+
let!(:store) { create :store }
|
6
|
+
let(:order) { Order.create }
|
7
|
+
|
8
|
+
let(:guitar) { create(:variant) }
|
9
|
+
let(:bass) { create(:variant) }
|
10
|
+
|
11
|
+
let(:bundle) { create(:product) }
|
12
|
+
|
13
|
+
subject { OrderContents.new(order) }
|
14
|
+
|
15
|
+
before { bundle.parts.push [guitar, bass] }
|
16
|
+
|
17
|
+
context "same variant within bundle and as regular product" do
|
18
|
+
let!(:guitar_item) { subject.add(guitar, 3) }
|
19
|
+
let!(:bundle_item) { subject.add(bundle.master, 5) }
|
20
|
+
|
21
|
+
it "destroys the variant as regular product only" do
|
22
|
+
subject.remove(guitar, 3)
|
23
|
+
expect(order.reload.line_items.to_a).to eq [bundle_item]
|
24
|
+
end
|
25
|
+
|
26
|
+
context "completed order" do
|
27
|
+
before do
|
28
|
+
order.create_proposed_shipments
|
29
|
+
order.touch :completed_at
|
30
|
+
end
|
31
|
+
|
32
|
+
it "destroys accurate number of inventory units" do
|
33
|
+
expect {
|
34
|
+
subject.remove(guitar, 3)
|
35
|
+
}.to change { InventoryUnit.count }.by(-3)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
describe OrderInventoryAssembly do
|
5
|
+
let(:order) { create(:order_with_line_items) }
|
6
|
+
let(:line_item) { order.line_items.first }
|
7
|
+
let(:bundle) { line_item.product }
|
8
|
+
let(:parts) { (1..3).map { create(:variant) } }
|
9
|
+
|
10
|
+
before do
|
11
|
+
bundle.parts << [parts]
|
12
|
+
bundle.set_part_count(parts.first, 3)
|
13
|
+
|
14
|
+
line_item.update_attributes!(quantity: 3)
|
15
|
+
order.reload.create_proposed_shipments
|
16
|
+
order.finalize!
|
17
|
+
end
|
18
|
+
|
19
|
+
subject { OrderInventoryAssembly.new(line_item) }
|
20
|
+
|
21
|
+
context "inventory units count" do
|
22
|
+
it "calculates the proper value for the bundle" do
|
23
|
+
expected_units_count = line_item.quantity * bundle.assemblies_parts.to_a.sum(&:count)
|
24
|
+
expect(subject.inventory_units.count).to eql(expected_units_count)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "verify line item units" do
|
29
|
+
let!(:original_units_count) { subject.inventory_units.count }
|
30
|
+
|
31
|
+
context "quantity increases" do
|
32
|
+
before { subject.line_item.quantity += 1 }
|
33
|
+
|
34
|
+
it "inserts new inventory units for every bundle part" do
|
35
|
+
expected_units_count = original_units_count + bundle.assemblies_parts.to_a.sum(&:count)
|
36
|
+
subject.verify
|
37
|
+
expect(OrderInventoryAssembly.new(line_item.reload).inventory_units.count).to eql(expected_units_count)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "quantity decreases" do
|
42
|
+
before { subject.line_item.quantity -= 1 }
|
43
|
+
|
44
|
+
it "remove inventory units for every bundle part" do
|
45
|
+
expected_units_count = original_units_count - bundle.assemblies_parts.to_a.sum(&:count)
|
46
|
+
subject.verify
|
47
|
+
|
48
|
+
# needs to reload so that inventory units are fetched from updates order.shipments
|
49
|
+
updated_units_count = OrderInventoryAssembly.new(line_item.reload).inventory_units.count
|
50
|
+
expect(updated_units_count).to eql(expected_units_count)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
describe OrderInventory do
|
5
|
+
let!(:store) { create :store }
|
6
|
+
let(:order) { Order.create }
|
7
|
+
|
8
|
+
subject { OrderInventory.new(order, order.line_items.first) }
|
9
|
+
|
10
|
+
context "same variant within bundle and as regular product" do
|
11
|
+
let(:contents) { OrderContents.new(order) }
|
12
|
+
let(:guitar) { create(:variant) }
|
13
|
+
let(:bass) { create(:variant) }
|
14
|
+
|
15
|
+
let(:bundle) { create(:product) }
|
16
|
+
|
17
|
+
before { bundle.parts.push [guitar, bass] }
|
18
|
+
|
19
|
+
let!(:bundle_item) { contents.add(bundle.master, 5) }
|
20
|
+
let!(:guitar_item) { contents.add(guitar, 3) }
|
21
|
+
|
22
|
+
let!(:shipment) { order.create_proposed_shipments.first }
|
23
|
+
|
24
|
+
context "completed order" do
|
25
|
+
before { order.touch :completed_at }
|
26
|
+
|
27
|
+
it "removes only units associated with provided line item" do
|
28
|
+
expect {
|
29
|
+
subject.send(:remove_from_shipment, shipment, 5)
|
30
|
+
}.not_to change { bundle_item.inventory_units.count }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Spree::Product do
|
4
|
+
before(:each) do
|
5
|
+
@product = FactoryGirl.create(:product, :name => "Foo Bar")
|
6
|
+
@master_variant = Spree::Variant.where(is_master: true).find_by_product_id(@product.id)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "Spree::Product Assembly" do
|
10
|
+
before(:each) do
|
11
|
+
@product = create(:product)
|
12
|
+
@part1 = create(:product, :can_be_part => true)
|
13
|
+
@part2 = create(:product, :can_be_part => true)
|
14
|
+
@product.add_part @part1.master, 1
|
15
|
+
@product.add_part @part2.master, 4
|
16
|
+
end
|
17
|
+
|
18
|
+
it "is an assembly" do
|
19
|
+
@product.should be_assembly
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
it "cannot be part" do
|
24
|
+
@product.should be_assembly
|
25
|
+
@product.can_be_part = true
|
26
|
+
@product.valid?
|
27
|
+
@product.errors[:can_be_part].should == ["assembly can't be part"]
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'changing part qty changes count on_hand' do
|
31
|
+
@product.set_part_count(@part2.master, 2)
|
32
|
+
@product.count_of(@part2.master).should == 2
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
describe Shipment do
|
5
|
+
context "order has one product assembly" do
|
6
|
+
let(:order) { Order.create }
|
7
|
+
let(:bundle) { create(:variant) }
|
8
|
+
let!(:parts) { (1..2).map { create(:variant) } }
|
9
|
+
let!(:bundle_parts) { bundle.product.parts << parts }
|
10
|
+
|
11
|
+
let!(:line_item) { order.contents.add(bundle, 1) }
|
12
|
+
let!(:shipment) { order.create_proposed_shipments.first }
|
13
|
+
|
14
|
+
before { order.update_column :state, 'complete' }
|
15
|
+
|
16
|
+
it "shipment item cost equals line item amount" do
|
17
|
+
expect(shipment.item_cost).to eq line_item.amount
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "manifests" do
|
22
|
+
include_context "product is ordered as individual and within a bundle"
|
23
|
+
|
24
|
+
let(:shipments) { order.create_proposed_shipments }
|
25
|
+
|
26
|
+
context "default" do
|
27
|
+
let(:expected_variants) { order.variants - [bundle_variant] + bundle.parts }
|
28
|
+
|
29
|
+
it "separates variant purchased individually from the bundle one" do
|
30
|
+
expect(shipments.count).to eql 1
|
31
|
+
shipments.first.manifest.map(&:variant).sort.should == expected_variants.sort
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "line items manifest" do
|
36
|
+
let(:expected_variants) { order.variants }
|
37
|
+
|
38
|
+
it "groups units by line_item only" do
|
39
|
+
expect(shipments.count).to eql 1
|
40
|
+
shipments.first.line_item_manifest.map(&:variant).sort.should == expected_variants.sort
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "units are not associated with a line item" do
|
45
|
+
let(:order) { create(:shipped_order) }
|
46
|
+
let(:shipment) { order.shipments.first }
|
47
|
+
|
48
|
+
it "searches for line item if inventory unit doesn't have one" do
|
49
|
+
shipment.manifest.last.line_item.should_not be_blank
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "set up new inventory units" do
|
55
|
+
let(:line_item) { create(:line_item) }
|
56
|
+
let(:variant) { line_item.variant }
|
57
|
+
let(:order) { line_item.order }
|
58
|
+
let(:shipment) { create(:shipment) }
|
59
|
+
|
60
|
+
it "assigns variant, order and line_item" do
|
61
|
+
unit = shipment.set_up_inventory('on_hand', variant, order, line_item)
|
62
|
+
|
63
|
+
expect(unit.line_item).to eq line_item
|
64
|
+
expect(unit.variant).to eq variant
|
65
|
+
expect(unit.order).to eq order
|
66
|
+
expect(unit.state).to eq 'on_hand'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "unit states for variant sold as part of an assembly and separately" do
|
71
|
+
let(:assembly_line_item) { create(:line_item) }
|
72
|
+
let(:shirt) { create(:variant) }
|
73
|
+
|
74
|
+
let(:assembly_shirts) do
|
75
|
+
5.times.map {
|
76
|
+
create(:inventory_unit,
|
77
|
+
variant: shirt,
|
78
|
+
line_item: assembly_line_item,
|
79
|
+
state: :on_hand)
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
let(:standalone_line_item) { create(:line_item, variant: shirt) }
|
84
|
+
|
85
|
+
let(:standalone_shirts) do
|
86
|
+
2.times.map {
|
87
|
+
create(:inventory_unit,
|
88
|
+
variant: shirt,
|
89
|
+
line_item: standalone_line_item,
|
90
|
+
state: :on_hand)
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
let(:shipment) { create(:shipment) }
|
95
|
+
|
96
|
+
before do
|
97
|
+
shipment.inventory_units << assembly_shirts
|
98
|
+
shipment.inventory_units << standalone_shirts
|
99
|
+
end
|
100
|
+
|
101
|
+
it "set states numbers properly for all items" do
|
102
|
+
shipment.manifest.each do |item|
|
103
|
+
if item.line_item.id == standalone_line_item.id
|
104
|
+
expect(item.states["on_hand"]).to eq standalone_shirts.count
|
105
|
+
else
|
106
|
+
expect(item.states["on_hand"]).to eq assembly_shirts.count
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|