Class: Spree::OrderShipping

Inherits:
Object
  • Object
show all
Defined in:
app/models/spree/order_shipping.rb

Overview

A service layer that handles generating Carton objects when inventory units are actually shipped. It also takes care of things like updating order and shipment states and delivering shipment emails as needed.

Instance Method Summary collapse

Constructor Details

#initialize(order) ⇒ OrderShipping

Returns a new instance of OrderShipping.



7
8
9
# File 'app/models/spree/order_shipping.rb', line 7

def initialize(order)
  @order = order
end

Instance Method Details

#ship(inventory_units:, stock_location:, address:, shipping_method:, shipped_at: Time.current, external_number: nil, tracking_number: nil, suppress_mailer: false) ⇒ Object

Generate a carton from the supplied inventory units and marks those units as shipped. Also sends shipment emails if appropriate and updates shipment_states for associated orders.

Parameters:

  • inventory_units

    The units to put in a carton together.

  • stock_location

    The location the carton shipped from.

  • address

    The address the carton was shipped to.

  • shipping_method

    Shipping method used for the carton.

  • shipped_at (defaults to: Time.current)

    The time at which the shipment was shipped.

  • external_number (defaults to: nil)

    An optional external number. e.g. from a shipping company or 3PL.

  • tracking_number (defaults to: nil)

    An option tracking number.

Returns:

  • The carton created.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'app/models/spree/order_shipping.rb', line 45

def ship(inventory_units:, stock_location:, address:, shipping_method:,
         shipped_at: Time.current, external_number: nil, tracking_number: nil, suppress_mailer: false)

  carton = nil

  Spree::InventoryUnit.transaction do
    inventory_units.each(&:ship!)

    carton = Spree::Carton.create!(
      stock_location:,
      address:,
      shipping_method:,
      inventory_units:,
      shipped_at:,
      external_number:,
      tracking: tracking_number
    )
  end

  inventory_units.map(&:shipment).uniq.each do |shipment|
    if shipment.inventory_units.reload.all? { |iu| iu.shipped? || iu.canceled? }
      shipment.update!(state: "shipped", shipped_at: Time.current, tracking: tracking_number)
    else
      shipment.update!(tracking: tracking_number)
    end
  end

  send_shipment_emails(carton) if stock_location.fulfillable? && !suppress_mailer # e.g. digital gift cards that aren't actually shipped
  @order.shipments.reload
  @order.recalculate

  carton
end

#ship_shipment(shipment, external_number: nil, tracking_number: nil, suppress_mailer: false) ⇒ Object

A shortcut method that ships all inventory units in a shipment in a single carton. See also #ship.

Parameters:

  • shipment

    The shipment to create a carton from.

  • external_number (defaults to: nil)

    An optional external number. e.g. from a shipping company or 3PL.

  • tracking_number (defaults to: nil)

    An optional tracking number.

Returns:

  • The carton created.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'app/models/spree/order_shipping.rb', line 18

def ship_shipment(shipment, external_number: nil, tracking_number: nil, suppress_mailer: false)
  ship(
    inventory_units: shipment.inventory_units.shippable,
    stock_location: shipment.stock_location,
    address: shipment.order.ship_address,
    shipping_method: shipment.shipping_method,
    shipped_at: Time.current,
    external_number:,
    # TODO: Remove the `|| shipment.tracking` once Shipment#ship! is called by
    # OrderShipping#ship rather than vice versa
    tracking_number: tracking_number || shipment.tracking,
    suppress_mailer:
  )
end