require 'spec_helper' module Spree describe OrderInventoryAssembly do describe "#verify" do context "when line item involves variants that are not user-selectable" do context "when a shipment is provided" do context "when the bundle is created" do it "produces inventory units for each item in the bundle" do shipment, line_item, variants = create_line_item_for_bundle( parts: [{ count: 1 }, { count: 1 }, { count: 3 }] ) inventory = OrderInventoryAssembly.new(line_item) inventory.verify(shipment) expect(inventory.inventory_units.count).to eq 5 expect(shipment.inventory_units_for(variants[0]).count).to eq 1 expect(shipment.inventory_units_for(variants[1]).count).to eq 1 expect(shipment.inventory_units_for(variants[2]).count).to eq 3 end end context "when the bundle quantity is increased" do it "adds [difference in quantity] sets of inventory units" do shipment, line_item, variants = create_line_item_for_bundle( parts: [{ count: 1 }, { count: 1 }, { count: 3 }] ) inventory = OrderInventoryAssembly.new(line_item) inventory.verify(shipment) expect(inventory.inventory_units.count).to eq 5 expect(shipment.inventory_units_for(variants[0]).count).to eq 1 expect(shipment.inventory_units_for(variants[1]).count).to eq 1 expect(shipment.inventory_units_for(variants[2]).count).to eq 3 line_item.update_column(:quantity, 2) inventory.verify(shipment) expect(inventory.inventory_units.count).to eq 10 expect(shipment.inventory_units_for(variants[0]).count).to eq 2 expect(shipment.inventory_units_for(variants[1]).count).to eq 2 expect(shipment.inventory_units_for(variants[2]).count).to eq 6 end end context "when the bundle quantity is decreased" do it "removes [difference in quantity] sets of inventory units" do shipment, line_item, variants = create_line_item_for_bundle( line_item_quantity: 2, parts: [{ count: 1 }, { count: 1 }, { count: 3 }] ) inventory = OrderInventoryAssembly.new(line_item) inventory.verify(shipment) expect(inventory.inventory_units.count).to eq 10 expect(shipment.inventory_units_for(variants[0]).count).to eq 2 expect(shipment.inventory_units_for(variants[1]).count).to eq 2 expect(shipment.inventory_units_for(variants[2]).count).to eq 6 line_item.update_column(:quantity, 1) inventory.verify(shipment) expect(inventory.inventory_units.count).to eq 5 expect(shipment.inventory_units_for(variants[0]).count).to eq 1 expect(shipment.inventory_units_for(variants[1]).count).to eq 1 expect(shipment.inventory_units_for(variants[2]).count).to eq 3 end end end context "when a shipment is not provided" do context "when the bundle is created" do it "produces inventory units for each item in the bundle" do shipment, line_item, variants = create_line_item_for_bundle( parts: [{ count: 1 }, { count: 1 }, { count: 3 }] ) inventory = OrderInventoryAssembly.new(line_item) inventory.verify expect(inventory.inventory_units.count).to eq 5 expect(shipment.inventory_units_for(variants[0]).count).to eq 1 expect(shipment.inventory_units_for(variants[1]).count).to eq 1 expect(shipment.inventory_units_for(variants[2]).count).to eq 3 end end context "when the bundle quantity is increased" do it "adds [difference in quantity] sets of inventory units" do shipment, line_item, variants = create_line_item_for_bundle( parts: [{ count: 1 }, { count: 1 }, { count: 3 }] ) inventory = OrderInventoryAssembly.new(line_item) inventory.verify expect(inventory.inventory_units.count).to eq 5 expect(shipment.inventory_units_for(variants[0]).count).to eq 1 expect(shipment.inventory_units_for(variants[1]).count).to eq 1 expect(shipment.inventory_units_for(variants[2]).count).to eq 3 line_item.update_column(:quantity, 2) inventory.verify expect(inventory.inventory_units.count).to eq 10 expect(shipment.inventory_units_for(variants[0]).count).to eq 2 expect(shipment.inventory_units_for(variants[1]).count).to eq 2 expect(shipment.inventory_units_for(variants[2]).count).to eq 6 end end context "when the bundle quantity is decreased" do it "removes [difference in quantity] sets of inventory units" do shipment, line_item, variants = create_line_item_for_bundle( line_item_quantity: 2, parts: [{ count: 1 }, { count: 1 }, { count: 3 }] ) inventory = OrderInventoryAssembly.new(line_item) inventory.verify expect(inventory.inventory_units.count).to eq 10 expect(shipment.inventory_units_for(variants[0]).count).to eq 2 expect(shipment.inventory_units_for(variants[1]).count).to eq 2 expect(shipment.inventory_units_for(variants[2]).count).to eq 6 line_item.update_column(:quantity, 1) inventory.verify expect(inventory.inventory_units.count).to eq 5 expect(shipment.inventory_units_for(variants[0]).count).to eq 1 expect(shipment.inventory_units_for(variants[1]).count).to eq 1 expect(shipment.inventory_units_for(variants[2]).count).to eq 3 end context "when the bundle has shipped and unshipped shipments" do it "removes the items from only the unshipped shipments" do unshipped_shipment, line_item, variants = create_line_item_for_bundle( line_item_quantity: 2, parts: [{ count: 1 }, { count: 1 }, { count: 3 }] ) shipped_shipment = create(:shipment, state: 'shipped') InventoryUnit.all[0..2].each do |unit| unit.update_attribute(:shipment_id, shipped_shipment.id) end inventory = OrderInventoryAssembly.new(line_item) line_item.update_column(:quantity, 1) inventory.verify expect(inventory.inventory_units.count).to eq 6 unshipped_units = unshipped_shipment.inventory_units expect(unshipped_units.count).to eq 3 unshipped_units.each do |unit| expect(unit.variant).to eq variants[2] end shipped_units = shipped_shipment.inventory_units expect(shipped_units.count).to eq 3 shipped_units[0..1].each do |unit| expect(unit.variant).to eq variants[0] end expect(shipped_units[2].variant).to eq variants[1] end end end end end context "when line item involves user-selectable variants" do context "when a shipment is provided" do context "when the bundle is created" do it "produces inventory units for each item in the bundle" do shipment, line_item, variants = create_line_item_for_bundle( parts: [ { count: 1 }, { count: 1 }, { count: 3, variant_selection_deferred: true } ] ) inventory = OrderInventoryAssembly.new(line_item) inventory.verify(shipment) expect(shipment.inventory_units_for(variants[0]).count).to eq 1 expect(shipment.inventory_units_for(variants[1]).count).to eq 1 expect(shipment.inventory_units_for(variants[2]).count).to eq 3 end end context "when the bundle quantity is increased" do it "adds [difference in quantity] sets of inventory units" do shipment, line_item, variants = create_line_item_for_bundle( parts: [ { count: 1 }, { count: 1 }, { count: 3, variant_selection_deferred: true } ] ) inventory = OrderInventoryAssembly.new(line_item) inventory.verify(shipment) expect(shipment.inventory_units_for(variants[0]).count).to eq 1 expect(shipment.inventory_units_for(variants[1]).count).to eq 1 expect(shipment.inventory_units_for(variants[2]).count).to eq 3 line_item.update_column(:quantity, 2) inventory.verify(shipment) expect(shipment.inventory_units_for(variants[0]).count).to eq 2 expect(shipment.inventory_units_for(variants[1]).count).to eq 2 expect(shipment.inventory_units_for(variants[2]).count).to eq 6 end end context "when the bundle quantity is decreased" do it "removes [difference in quantity] sets of inventory units" do shipment, line_item, variants = create_line_item_for_bundle( line_item_quantity: 2, parts: [ { count: 1 }, { count: 1 }, { count: 3, variant_selection_deferred: true } ] ) inventory = OrderInventoryAssembly.new(line_item) inventory.verify(shipment) expect(shipment.inventory_units_for(variants[0]).count).to eq 2 expect(shipment.inventory_units_for(variants[1]).count).to eq 2 expect(shipment.inventory_units_for(variants[2]).count).to eq 6 line_item.update_column(:quantity, 1) inventory.verify(shipment) expect(shipment.inventory_units_for(variants[0]).count).to eq 1 expect(shipment.inventory_units_for(variants[1]).count).to eq 1 expect(shipment.inventory_units_for(variants[2]).count).to eq 3 end end end end end def create_line_item_for_bundle(args) parts = args.fetch(:parts) line_item_quantity = args.fetch(:line_item_quantity, 1) order = create(:order, completed_at: Time.now) shipment = create(:shipment, order: order) bundle = create(:product, name: "Bundle") red_option = create(:option_value, presentation: "Red") blue_option = create(:option_value, presentation: "Blue") option_type = create(:option_type, presentation: "Color", name: "color", option_values: [ red_option, blue_option ]) variants = [] selected_variants = {} parts.each do |part| product_properties = { can_be_part: true } if part[:variant_selection_deferred] product_properties[:option_types] = [option_type] end product = create(:product_in_stock, product_properties) assemblies_part_attributes = { assembly: bundle }.merge(part) if part[:variant_selection_deferred] create(:variant_in_stock, product: product, option_values: [red_option]) variants << create(:variant_in_stock, product: product, option_values: [blue_option]) else variants << product.master end assemblies_part_attributes[:part] = product.master create(:assemblies_part, assemblies_part_attributes) if part[:variant_selection_deferred] selected_variants = { "selected_variants" => { "#{bundle.assemblies_parts.last.id}" => "#{variants.last.id}" } } end end bundle.reload contents = Spree::OrderContents.new(order) line_item = contents.add_to_line_item_with_parts( bundle.master, line_item_quantity, selected_variants ) line_item.reload [shipment, line_item, variants] end end end