<commit_before>require 'spec_helper'

module Spree
  describe LineItem do
    describe "scopes" do
      let(:o) { create(:order) }

      let(:s1) { create(:supplier_enterprise) }
      let(:s2) { create(:supplier_enterprise) }

      let(:p1) { create(:simple_product, supplier: s1) }
      let(:p2) { create(:simple_product, supplier: s2) }

      let(:li1) { create(:line_item, order: o, product: p1) }
      let(:li2) { create(:line_item, order: o, product: p2) }

      let(:p3) { create(:product, name: 'Clear Honey') }
      let(:p4) { create(:product, name: 'Apricots') }
      let(:v1) { create(:variant, product: p3, unit_value: 500) }
      let(:v2) { create(:variant, product: p3, unit_value: 250) }
      let(:v3) { create(:variant, product: p4, unit_value: 500, display_name: "ZZ") }
      let(:v4) { create(:variant, product: p4, unit_value: 500, display_name: "aa") }
      let(:li3) { create(:line_item, order: o, product: p3, variant: v1) }
      let(:li4) { create(:line_item, order: o, product: p3, variant: v2) }
      let(:li5) { create(:line_item, order: o, product: p4, variant: v3) }
      let(:li6) { create(:line_item, order: o, product: p4, variant: v4) }

      let(:oc_order) { create :order_with_totals_and_distribution }

      it "finds line items for products supplied by a particular enterprise" do
        expect(LineItem.supplied_by(s1)).to eq([li1])
        expect(LineItem.supplied_by(s2)).to eq([li2])
      end

      it "finds line items for products supplied by one of a number of enterprises" do
        expect(LineItem.supplied_by_any([s1])).to eq([li1])
        expect(LineItem.supplied_by_any([s2])).to eq([li2])
        expect(LineItem.supplied_by_any([s1, s2])).to match_array [li1, li2]
      end

      describe "finding line items with and without tax" do
        let(:tax_rate) { create(:tax_rate, calculator: Spree::Calculator::DefaultTax.new) }
        let!(:adjustment1) { create(:adjustment, adjustable: li1, originator: tax_rate, label: "TR", amount: 123, included_tax: 10.00) }
        let!(:adjustment2) { create(:adjustment, adjustable: li1, originator: tax_rate, label: "TR", amount: 123, included_tax: 10.00) }

        before { li1; li2 }

        it "finds line items with tax" do
          expect(LineItem.with_tax).to eq([li1])
        end

        it "finds line items without tax" do
          expect(LineItem.without_tax).to eq([li2])
        end
      end

      it "finds line items sorted by name and unit_value" do
        expect(o.line_items.sorted_by_name_and_unit_value).to eq([li6, li5, li4, li3])
      end

      it "finds line items from a given order cycle" do
        expect(LineItem.from_order_cycle(oc_order.order_cycle).first.id).to eq oc_order.line_items.first.id
      end
    end

    describe "capping quantity at stock level" do
      let!(:v) { create(:variant, on_demand: false, on_hand: 10) }
      let!(:li) { create(:line_item, variant: v, quantity: 10, max_quantity: 10) }

      before do
        v.update_attributes! on_hand: 5
      end

      it "caps quantity" do
        li.cap_quantity_at_stock!
        expect(li.reload.quantity).to eq 5
      end

      it "does not cap max_quantity" do
        li.cap_quantity_at_stock!
        expect(li.reload.max_quantity).to eq 10
      end

      it "works for products without max_quantity" do
        li.update_column :max_quantity, nil
        li.cap_quantity_at_stock!
        li.reload
        expect(li.quantity).to eq 5
        expect(li.max_quantity).to be nil
      end

      it "does nothing for on_demand items" do
        v.update_attributes! on_demand: true
        li.cap_quantity_at_stock!
        li.reload
        expect(li.quantity).to eq 10
        expect(li.max_quantity).to eq 10
      end

      it "caps at zero when stock is negative" do
        v.update_attributes! on_hand: -2
        li.cap_quantity_at_stock!
        expect(li.reload.quantity).to eq 0
      end

      context "when a variant override is in place" do
        let!(:hub) { create(:distributor_enterprise) }
        let!(:vo) { create(:variant_override, hub: hub, variant: v, count_on_hand: 2) }

        before do
          li.order.update_attributes(distributor_id: hub.id)

          # li#scoper is memoised, and this makes it difficult to update test conditions
          # so we reset it after the line_item is created for each spec
          li.remove_instance_variable(:@scoper)
        end

        it "caps quantity to override stock level" do
          li.cap_quantity_at_stock!
          expect(li.quantity).to eq 2
        end

        context "when count on hand is negative" do
          before { vo.update_attributes(count_on_hand: -3) }

          it "caps at zero" do
            v.update_attributes(on_hand: -2)
            li.cap_quantity_at_stock!
            expect(li.reload.quantity).to eq 0
          end
        end
      end
    end

    describe "reducing stock levels on order completion" do
      context "when the item is on_demand" do
        let!(:hub) { create(:distributor_enterprise) }
        let(:bill_address) { create(:address) }
        let!(:variant_on_demand) { create(:variant, on_demand: true, on_hand: 1) }
        let!(:order) {
          create(:order_with_totals_and_distribution,
                 distributor: hub,
                 bill_address: bill_address,
                 ship_address: bill_address)
        }
        let!(:shipping_method) { create(:shipping_method, distributors: [hub]) }
        let!(:line_item) { create(:line_item, variant: variant_on_demand, quantity: 10, order: order) }

        before do
          order.update_totals
          order.payments << create(:payment, amount: order.total)
          until order.completed? do break unless order.next! end
          order.payment_state = 'paid'
          order.select_shipping_method(shipping_method.id)
          order.shipment.update!(order)
        end

        xit "creates a shipment without backordered items" do
          expect(order.shipment.manifest.first.quantity).to eq 10
          expect(order.shipment.manifest.first.states).to eq 'on_hand' => 10
          expect(order.shipment.manifest.first.variant).to eq line_item.variant
        end

        it "does not reduce the variant's stock level" do
          expect(variant_on_demand.reload.on_hand).to eq 1
        end

        it "does not mark inventory units as backorderd" do
          backordered_units = order.shipments.first.inventory_units.any?(&:backordered?)
          expect(backordered_units).to be false
        end

        it "does not mark the shipment as backorderd" do
          expect(order.shipments.first.backordered?).to be false<commit_msg>Stabilise spec by not creating noise data<commit_after>require 'spec_helper'

module Spree
  describe LineItem do
    describe "scopes" do
      let(:o) { create(:order) }

      let(:s1) { create(:supplier_enterprise) }
      let(:s2) { create(:supplier_enterprise) }

      let(:p1) { create(:simple_product, supplier: s1) }
      let(:p2) { create(:simple_product, supplier: s2) }

      let(:li1) { create(:line_item, order: o, product: p1) }
      let(:li2) { create(:line_item, order: o, product: p2) }

      let(:p3) { create(:product, name: 'Clear Honey') }
      let(:p4) { create(:product, name: 'Apricots') }
      let(:v1) { create(:variant, product: p3, unit_value: 500) }
      let(:v2) { create(:variant, product: p3, unit_value: 250) }
      let(:v3) { create(:variant, product: p4, unit_value: 500, display_name: "ZZ") }
      let(:v4) { create(:variant, product: p4, unit_value: 500, display_name: "aa") }
      let(:li3) { create(:line_item, order: o, product: p3, variant: v1) }
      let(:li4) { create(:line_item, order: o, product: p3, variant: v2) }
      let(:li5) { create(:line_item, order: o, product: p4, variant: v3) }
      let(:li6) { create(:line_item, order: o, product: p4, variant: v4) }

      let(:oc_order) { create :order_with_totals_and_distribution }

      it "finds line items for products supplied by a particular enterprise" do
        expect(LineItem.supplied_by(s1)).to eq([li1])
        expect(LineItem.supplied_by(s2)).to eq([li2])
      end

      it "finds line items for products supplied by one of a number of enterprises" do
        expect(LineItem.supplied_by_any([s1])).to eq([li1])
        expect(LineItem.supplied_by_any([s2])).to eq([li2])
        expect(LineItem.supplied_by_any([s1, s2])).to match_array [li1, li2]
      end

      describe "finding line items with and without tax" do
        let(:tax_rate) { create(:tax_rate, calculator: Spree::Calculator::DefaultTax.new) }
        let!(:adjustment1) { create(:adjustment, adjustable: li1, originator: tax_rate, label: "TR", amount: 123, included_tax: 10.00) }
        let!(:adjustment2) { create(:adjustment, adjustable: li1, originator: tax_rate, label: "TR", amount: 123, included_tax: 10.00) }

        before { li1; li2 }

        it "finds line items with tax" do
          expect(LineItem.with_tax).to eq([li1])
        end

        it "finds line items without tax" do
          expect(LineItem.without_tax).to eq([li2])
        end
      end

      it "finds line items sorted by name and unit_value" do
        expect(o.line_items.sorted_by_name_and_unit_value).to eq([li6, li5, li4, li3])
      end

      it "finds line items from a given order cycle" do
        expect(LineItem.from_order_cycle(oc_order.order_cycle).first.id).to eq oc_order.line_items.first.id
      end
    end

    describe "capping quantity at stock level" do
      let!(:v) { create(:variant, on_demand: false, on_hand: 10) }
      let!(:li) { create(:line_item, variant: v, quantity: 10, max_quantity: 10) }

      before do
        v.update_attributes! on_hand: 5
      end

      it "caps quantity" do
        li.cap_quantity_at_stock!
        expect(li.reload.quantity).to eq 5
      end

      it "does not cap max_quantity" do
        li.cap_quantity_at_stock!
        expect(li.reload.max_quantity).to eq 10
      end

      it "works for products without max_quantity" do
        li.update_column :max_quantity, nil
        li.cap_quantity_at_stock!
        li.reload
        expect(li.quantity).to eq 5
        expect(li.max_quantity).to be nil
      end

      it "does nothing for on_demand items" do
        v.update_attributes! on_demand: true
        li.cap_quantity_at_stock!
        li.reload
        expect(li.quantity).to eq 10
        expect(li.max_quantity).to eq 10
      end

      it "caps at zero when stock is negative" do
        v.update_attributes! on_hand: -2
        li.cap_quantity_at_stock!
        expect(li.reload.quantity).to eq 0
      end

      context "when a variant override is in place" do
        let!(:hub) { create(:distributor_enterprise) }
        let!(:vo) { create(:variant_override, hub: hub, variant: v, count_on_hand: 2) }

        before do
          li.order.update_attributes(distributor_id: hub.id)

          # li#scoper is memoised, and this makes it difficult to update test conditions
          # so we reset it after the line_item is created for each spec
          li.remove_instance_variable(:@scoper)
        end

        it "caps quantity to override stock level" do
          li.cap_quantity_at_stock!
          expect(li.quantity).to eq 2
        end

        context "when count on hand is negative" do
          before { vo.update_attributes(count_on_hand: -3) }

          it "caps at zero" do
            v.update_attributes(on_hand: -2)
            li.cap_quantity_at_stock!
            expect(li.reload.quantity).to eq 0
          end
        end
      end
    end

    describe "reducing stock levels on order completion" do
      context "when the item is on_demand" do
        let!(:hub) { create(:distributor_enterprise) }
        let(:bill_address) { create(:address) }
        let!(:variant_on_demand) { create(:variant, on_demand: true, on_hand: 1) }
        let!(:order) {
          create(:order,
                 distributor: hub,
                 order_cycle: create(:simple_order_cycle),
                 bill_address: bill_address,
                 ship_address: bill_address)
        }
        let!(:shipping_method) { create(:shipping_method, distributors: [hub]) }
        let!(:line_item) { create(:line_item, variant: variant_on_demand, quantity: 10, order: order) }

        before do
          order.reload
          order.update_totals
          order.payments << create(:payment, amount: order.total)
          until order.completed? do break unless order.next! end
          order.payment_state = 'paid'
          order.select_shipping_method(shipping_method.id)
          order.shipment.update!(order)
        end

        it "creates a shipment without backordered items" do
          expect(order.shipment.manifest.count).to eq 1
          expect(order.shipment.manifest.first.quantity).to eq 10
          expect(order.shipment.manifest.first.states).to eq 'on_hand' => 10
          expect(order.shipment.manifest.first.variant).to eq line_item.variant
        end

        it "does not reduce the variant's stock level" do
          expect(variant_on_demand.reload.on_hand).to eq 1
        end

        it "does not mark inventory units as backorderd" do
          backordered_units = order.shipments.first.inventory_units.any?(&:backordered?)
          expect(backordered_units).to be false
        end

        it "does not mark the shipment as backorderd" do
          expect(order.shipments.first.backordered?).to be false
{'fraction_non_alphanumeric': 0.1076923076923077, 'fraction_numerical': 0.01664201183431953, 'mean_word_length': 2.5931437682699974, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1063105', 'n_tokens_mistral': 4427, 'n_tokens_neox': 4156, 'n_words': 1121}