<commit_before>module Spree
  module Core
    module Importer
      class Order

        def self.import(user, params)
          ActiveRecord::Base.transaction do
            ensure_country_id_from_params params[:ship_address_attributes]
            ensure_state_id_from_params params[:ship_address_attributes]
            ensure_country_id_from_params params[:bill_address_attributes]
            ensure_state_id_from_params params[:bill_address_attributes]

            create_params = params.slice :currency
            order = Spree::Order.create! create_params
            order.store ||= Spree::Store.default
            order.associate_user!(user)
            order.save!

            shipments_attrs = params.delete(:shipments_attributes)

            create_shipments_from_params(shipments_attrs, order)
            create_line_items_from_params(params.delete(:line_items_attributes),order)
            create_adjustments_from_params(params.delete(:adjustments_attributes), order)
            create_payments_from_params(params.delete(:payments_attributes), order)

            params.delete(:user_id) unless user.try(:has_spree_role?, "admin") && params.key?(:user_id)

            completed_at = params.delete(:completed_at)

            order.update_attributes!(params)

            order.create_proposed_shipments unless shipments_attrs.present?

            if completed_at
              order.completed_at = completed_at
              order.state = 'complete'
              order.save!
            end

            # Really ensure that the order totals & states are correct
            order.updater.update
            if shipments_attrs.present?
              order.shipments.each_with_index do |shipment, index|
                shipment.update_columns(cost: shipments_attrs[index][:cost].to_f) if shipments_attrs[index][:cost].present?
              end
            end
            order.reload
          end
        end

        def self.create_shipments_from_params(shipments_hash, order)
          return [] unless shipments_hash

          line_items = order.line_items
          shipments_hash.each do |s|
            shipment = order.shipments.build
            shipment.tracking       = s[:tracking]
            shipment.stock_location = Spree::StockLocation.find_by_admin_name(s[:stock_location]) || Spree::StockLocation.find_by_name!(s[:stock_location])

            inventory_units = s[:inventory_units] || []
            inventory_units.each do |iu|
              ensure_variant_id_from_params(iu)

              unit = shipment.inventory_units.build
              unit.order = order

              # Spree expects a Inventory Unit to always reference a line
              # item and variant otherwise users might get exceptions when
              # trying to view these units. Note the Importer might not be
              # able to find the line item if line_item.variant_id |= iu.variant_id
              unit.variant_id = iu[:variant_id]
              if line_item = order.line_items.find_by(variant_id: iu[:variant_id])
                unit.line_item = line_item
              else
                unit.line_item = order.contents.add(Spree::Variant.find(iu[:variant_id]), 1)
              end
            end

            # Mark shipped if it should be.
            if s[:shipped_at].present?
              shipment.shipped_at = s[:shipped_at]
              shipment.state      = 'shipped'
              shipment.inventory_units.each do |unit|
                unit.state = 'shipped'
              end
            end

            shipment.save!

            shipping_method = Spree::ShippingMethod.find_by_name(s[:shipping_method]) || Spree::ShippingMethod.find_by_admin_name!(s[:shipping_method])
            rate = shipment.shipping_rates.create!(:shipping_method => shipping_method,
                                                   :cost => s[:cost])
            shipment.selected_shipping_rate_id = rate.id
            shipment.update_amounts
          end
        end

        def self.create_line_items_from_params(line_items_hash, order)
          return {} unless line_items_hash
          line_items_hash.each_key do |k|
            extra_params = line_items_hash[k].except(:variant_id, :quantity, :sku)
            line_item = ensure_variant_id_from_params(line_items_hash[k])
            line_item = order.contents.add(Spree::Variant.find(line_item[:variant_id]), line_item[:quantity])<commit_msg>Avoid updating order with partially built shipment<commit_after>module Spree
  module Core
    module Importer
      class Order

        def self.import(user, params)
          ActiveRecord::Base.transaction do
            ensure_country_id_from_params params[:ship_address_attributes]
            ensure_state_id_from_params params[:ship_address_attributes]
            ensure_country_id_from_params params[:bill_address_attributes]
            ensure_state_id_from_params params[:bill_address_attributes]

            create_params = params.slice :currency
            order = Spree::Order.create! create_params
            order.store ||= Spree::Store.default
            order.associate_user!(user)
            order.save!

            shipments_attrs = params.delete(:shipments_attributes)

            create_shipments_from_params(shipments_attrs, order)
            create_line_items_from_params(params.delete(:line_items_attributes),order)
            create_adjustments_from_params(params.delete(:adjustments_attributes), order)
            create_payments_from_params(params.delete(:payments_attributes), order)

            params.delete(:user_id) unless user.try(:has_spree_role?, "admin") && params.key?(:user_id)

            completed_at = params.delete(:completed_at)

            order.update_attributes!(params)

            order.create_proposed_shipments unless shipments_attrs.present?

            if completed_at
              order.completed_at = completed_at
              order.state = 'complete'
              order.save!
            end

            # Really ensure that the order totals & states are correct
            order.updater.update
            if shipments_attrs.present?
              order.shipments.each_with_index do |shipment, index|
                shipment.update_columns(cost: shipments_attrs[index][:cost].to_f) if shipments_attrs[index][:cost].present?
              end
            end
            order.reload
          end
        end

        def self.create_shipments_from_params(shipments_hash, order)
          return [] unless shipments_hash

          line_items = order.line_items
          shipments_hash.each do |s|
            shipment = Shipment.new
            shipment.tracking       = s[:tracking]
            shipment.stock_location = Spree::StockLocation.find_by_admin_name(s[:stock_location]) || Spree::StockLocation.find_by_name!(s[:stock_location])

            inventory_units = s[:inventory_units] || []
            inventory_units.each do |iu|
              ensure_variant_id_from_params(iu)

              unless line_item = order.line_items.find_by(variant_id: iu[:variant_id])
                line_item = order.contents.add(Spree::Variant.find(iu[:variant_id]), 1)
              end

              # Spree expects a Inventory Unit to always reference a line
              # item and variant otherwise users might get exceptions when
              # trying to view these units. Note the Importer might not be
              # able to find the line item if line_item.variant_id |= iu.variant_id
              shipment.inventory_units.new(
                order: order,
                variant_id: iu[:variant_id],
                line_item: line_item
              )
            end

            # Mark shipped if it should be.
            if s[:shipped_at].present?
              shipment.shipped_at = s[:shipped_at]
              shipment.state      = 'shipped'
              shipment.inventory_units.each do |unit|
                unit.state = 'shipped'
              end
            end

            order.shipments << shipment
            shipment.save!

            shipping_method = Spree::ShippingMethod.find_by_name(s[:shipping_method]) || Spree::ShippingMethod.find_by_admin_name!(s[:shipping_method])
            rate = shipment.shipping_rates.create!(:shipping_method => shipping_method,
                                                   :cost => s[:cost])
            shipment.selected_shipping_rate_id = rate.id
            shipment.update_amounts
          end
        end

        def self.create_line_items_from_params(line_items_hash, order)
          return {} unless line_items_hash
          line_items_hash.each_key do |k|
            extra_params = line_items_hash[k].except(:variant_id, :quantity, :sku)
            line_item = ensure_variant_id_from_params(line_items_hash[k])
            line_item = order.contents.add(Spree::Variant.find(line_item[:variant_id]), line_item[:quantity])
{'fraction_non_alphanumeric': 0.07762096774193548, 'fraction_numerical': 0.00022401433691756272, 'mean_word_length': 2.1787112851548596, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4769120', 'n_tokens_mistral': 2426, 'n_tokens_neox': 2344, 'n_words': 437}