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.



5
6
7
# File 'app/models/spree/order_shipping.rb', line 5

def initialize(order)
  @order = order
end

Instance Method Details

#ship(inventory_units:, stock_location:, address:, shipping_method:, shipped_at: Time.now, 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.now)

    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.



43
44
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
78
79
80
# File 'app/models/spree/order_shipping.rb', line 43

def ship(inventory_units:, stock_location:, address:, shipping_method:,
         shipped_at: Time.now, 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: stock_location,
      address: address,
      shipping_method: shipping_method,
      inventory_units: inventory_units,
      shipped_at: shipped_at,
      external_number: external_number,
      tracking: tracking_number,
    )
  end

  inventory_units.map(&:shipment).uniq.each do |shipment|
    # Temporarily propagate the tracking number to the shipment as well
    # TODO: Remove tracking numbers from shipments.
    shipment.update_attributes!(tracking: tracking_number)

    if shipment.inventory_units(true).all? {|iu| iu.shipped? || iu.canceled? }
      # TODO: make OrderShipping#ship_shipment call Shipment#ship! rather than
      # having Shipment#ship! call OrderShipping#ship_shipment. We only really
      # need this `update_columns` for the specs, until we make that change.
      shipment.update_columns(state: 'shipped', shipped_at: Time.now)
    end
  end

  send_shipment_email(carton) if stock_location.fulfillable? && !suppress_mailer # e.g. digital gift cards that aren't actually shipped
  fulfill_order_stock_locations(stock_location)
  update_order_state

  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.



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

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.address,
    shipping_method: shipment.shipping_method,
    shipped_at: Time.now,
    external_number: 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: suppress_mailer,
  )
end