Class: Spree::Shipment
Overview
An order’s planned shipments including tracking and cost.
Instance Attribute Summary collapse
-
#special_instructions ⇒ Object
TODO: remove the suppress_mailer temporary variable once we are calling ‘ship’ from outside of the state machine and can actually pass variables through.
-
#suppress_mailer ⇒ Object
TODO: remove the suppress_mailer temporary variable once we are calling ‘ship’ from outside of the state machine and can actually pass variables through.
Instance Method Summary
collapse
-
#add_shipping_method(shipping_method, selected = false) ⇒ Object
-
#address ⇒ Object
-
#after_cancel ⇒ Object
-
#after_resume ⇒ Object
-
#backordered? ⇒ Boolean
-
#can_transition_from_canceled_to_ready? ⇒ Boolean
-
#can_transition_from_pending_to_ready? ⇒ Boolean
-
#can_transition_from_pending_to_shipped? ⇒ Boolean
-
#currency ⇒ Object
-
#determine_state(order) ⇒ Object
Determines the appropriate state
according to the following logic:.
-
#discounted_cost ⇒ Object
(also: #discounted_amount)
-
#editable_by?(_user) ⇒ Boolean
-
#finalize! ⇒ Object
Decrement the stock counts for all pending inventory units in this shipment and mark.
-
#include?(variant) ⇒ Boolean
-
#inventory_units_for(variant) ⇒ Object
-
#inventory_units_for_item(line_item, variant = nil) ⇒ Object
-
#item_cost ⇒ Object
-
#manifest ⇒ Object
-
#ready_or_pending? ⇒ Boolean
-
#refresh_rates ⇒ Object
-
#requires_shipment? ⇒ Boolean
-
#select_shipping_method(shipping_method) ⇒ Object
-
#selected_shipping_rate ⇒ Object
-
#selected_shipping_rate_id ⇒ Object
-
#selected_shipping_rate_id=(id) ⇒ Object
-
#set_up_inventory(state, variant, _order, line_item) ⇒ Object
-
#shipped=(value) ⇒ Object
-
#shipping_method ⇒ Object
-
#tax_total ⇒ Object
Only one of either included_tax_total or additional_tax_total is set This method returns the total of the two.
-
#to_package ⇒ Object
-
#to_param ⇒ Object
-
#total ⇒ BigDecimal
(also: #final_price)
The amount of this shipment, taking into consideration all its adjustments.
-
#total_before_tax ⇒ BigDecimal
The amount of this item, taking into consideration all non-tax adjustments.
-
#total_excluding_vat ⇒ BigDecimal
(also: #pre_tax_amount)
The amount of this shipment before VAT tax.
-
#total_with_items ⇒ Object
(also: #final_price_with_items)
-
#tracking_url ⇒ Object
-
#transfer_to_location(variant, quantity, stock_location) ⇒ Object
-
#transfer_to_shipment(variant, quantity, shipment_to_transfer_to) ⇒ Object
-
#update!(order_or_attrs) ⇒ Object
-
#update_amounts ⇒ Object
-
#update_attributes_and_order(params = {}) ⇒ Object
Update Shipment and make sure Order states follow the shipment changes.
-
#update_state ⇒ Object
Updates the state of the Shipment bypassing any callbacks.
money_methods
Methods inherited from Base
display_includes, #initialize_preference_defaults, page, preference
#admin_form_preference_names, #default_preferences, #defined_preferences, #get_preference, #has_preference!, #has_preference?, #preference_default, #preference_type, #set_preference
Instance Attribute Details
#special_instructions ⇒ Object
TODO: remove the suppress_mailer temporary variable once we are calling ‘ship’ from outside of the state machine and can actually pass variables through.
24
25
26
|
# File 'app/models/spree/shipment.rb', line 24
def special_instructions
@special_instructions
end
|
#suppress_mailer ⇒ Object
TODO: remove the suppress_mailer temporary variable once we are calling ‘ship’ from outside of the state machine and can actually pass variables through.
24
25
26
|
# File 'app/models/spree/shipment.rb', line 24
def suppress_mailer
@suppress_mailer
end
|
Instance Method Details
#add_shipping_method(shipping_method, selected = false) ⇒ Object
106
107
108
|
# File 'app/models/spree/shipment.rb', line 106
def add_shipping_method(shipping_method, selected = false)
shipping_rates.create(shipping_method: shipping_method, selected: selected, cost: cost)
end
|
#address ⇒ Object
389
390
391
392
|
# File 'app/models/spree/shipment.rb', line 389
def address
Spree::Deprecation.warn("Calling Shipment#address is deprecated. Use Order#ship_address instead", caller)
order.ship_address if order
end
|
#after_cancel ⇒ Object
111
112
113
|
# File 'app/models/spree/shipment.rb', line 111
def after_cancel
manifest.each { |item| manifest_restock(item) }
end
|
#after_resume ⇒ Object
115
116
117
|
# File 'app/models/spree/shipment.rb', line 115
def after_resume
manifest.each { |item| manifest_unstock(item) }
end
|
#backordered? ⇒ Boolean
119
120
121
|
# File 'app/models/spree/shipment.rb', line 119
def backordered?
inventory_units.any?(&:backordered?)
end
|
#can_transition_from_canceled_to_ready? ⇒ Boolean
93
94
95
|
# File 'app/models/spree/shipment.rb', line 93
def can_transition_from_canceled_to_ready?
can_transition_from_pending_to_ready?
end
|
#can_transition_from_pending_to_ready? ⇒ Boolean
87
88
89
90
91
|
# File 'app/models/spree/shipment.rb', line 87
def can_transition_from_pending_to_ready?
order.can_ship? &&
inventory_units.all? { |iu| iu.shipped? || iu.allow_ship? || iu.canceled? } &&
(order.paid? || !Spree::Config[:require_payment_to_ship])
end
|
#can_transition_from_pending_to_shipped? ⇒ Boolean
83
84
85
|
# File 'app/models/spree/shipment.rb', line 83
def can_transition_from_pending_to_shipped?
!requires_shipment?
end
|
#currency ⇒ Object
123
124
125
|
# File 'app/models/spree/shipment.rb', line 123
def currency
order ? order.currency : Spree::Config[:currency]
end
|
#determine_state(order) ⇒ Object
Determines the appropriate state
according to the following logic:
canceled if order is canceled pending unless order is complete and order.payment_state
is paid
shipped if already shipped (ie. does not change the state) ready all other cases
261
262
263
264
265
266
267
268
269
270
|
# File 'app/models/spree/shipment.rb', line 261
def determine_state(order)
return 'canceled' if order.canceled?
return 'shipped' if shipped?
return 'pending' unless order.can_ship?
if can_transition_from_pending_to_ready?
'ready'
else
'pending'
end
end
|
#discounted_cost ⇒ Object
Also known as:
discounted_amount
127
128
129
|
# File 'app/models/spree/shipment.rb', line 127
def discounted_cost
cost + promo_total
end
|
#editable_by?(_user) ⇒ Boolean
162
163
164
|
# File 'app/models/spree/shipment.rb', line 162
def editable_by?(_user)
!shipped?
end
|
#finalize! ⇒ Object
Decrement the stock counts for all pending inventory units in this shipment and mark. Any previous non-pending inventory units are skipped as their stock had already been allocated.
170
171
172
|
# File 'app/models/spree/shipment.rb', line 170
def finalize!
finalize_pending_inventory_units
end
|
#include?(variant) ⇒ Boolean
174
175
176
|
# File 'app/models/spree/shipment.rb', line 174
def include?(variant)
inventory_units_for(variant).present?
end
|
#inventory_units_for(variant) ⇒ Object
178
179
180
|
# File 'app/models/spree/shipment.rb', line 178
def inventory_units_for(variant)
inventory_units.where(variant_id: variant.id)
end
|
#inventory_units_for_item(line_item, variant = nil) ⇒ Object
182
183
184
|
# File 'app/models/spree/shipment.rb', line 182
def inventory_units_for_item(line_item, variant = nil)
inventory_units.where(line_item_id: line_item.id, variant_id: line_item.variant.id || variant.id)
end
|
#item_cost ⇒ Object
186
187
188
|
# File 'app/models/spree/shipment.rb', line 186
def item_cost
line_items.map(&:total).sum
end
|
#manifest ⇒ Object
231
232
233
|
# File 'app/models/spree/shipment.rb', line 231
def manifest
@manifest ||= Spree::ShippingManifest.new(inventory_units: inventory_units).items
end
|
#ready_or_pending? ⇒ Boolean
190
191
192
|
# File 'app/models/spree/shipment.rb', line 190
def ready_or_pending?
ready? || pending?
end
|
#refresh_rates ⇒ Object
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
# File 'app/models/spree/shipment.rb', line 194
def refresh_rates
return shipping_rates if shipped?
return [] unless can_get_rates?
original_shipping_method_id = shipping_method.try!(:id)
new_rates = Spree::Config.stock.estimator_class.new.shipping_rates(to_package)
selected_rate = new_rates.detect{ |rate| rate.shipping_method_id == original_shipping_method_id }
if selected_rate
new_rates.each do |rate|
rate.selected = (rate == selected_rate)
end
end
self.shipping_rates = new_rates
save!
shipping_rates
end
|
#requires_shipment? ⇒ Boolean
385
386
387
|
# File 'app/models/spree/shipment.rb', line 385
def requires_shipment?
!stock_location || stock_location.fulfillable?
end
|
#select_shipping_method(shipping_method) ⇒ Object
219
220
221
222
223
224
225
|
# File 'app/models/spree/shipment.rb', line 219
def select_shipping_method(shipping_method)
estimator = Spree::Config.stock.estimator_class.new
rates = estimator.shipping_rates(to_package, false)
rate = rates.detect { |r| r.shipping_method_id == shipping_method.id }
rate.selected = true
self.shipping_rates = [rate]
end
|
#selected_shipping_rate ⇒ Object
227
228
229
|
# File 'app/models/spree/shipment.rb', line 227
def selected_shipping_rate
shipping_rates.detect(&:selected?)
end
|
#selected_shipping_rate_id ⇒ Object
235
236
237
|
# File 'app/models/spree/shipment.rb', line 235
def selected_shipping_rate_id
selected_shipping_rate.try(:id)
end
|
#selected_shipping_rate_id=(id) ⇒ Object
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
|
# File 'app/models/spree/shipment.rb', line 239
def selected_shipping_rate_id=(id)
return if selected_shipping_rate_id == id
new_rate = shipping_rates.detect { |rate| rate.id == id.to_i }
unless new_rate
fail(
ArgumentError,
"Could not find shipping rate id #{id} for shipment #{number}"
)
end
transaction do
selected_shipping_rate.update!(selected: false) if selected_shipping_rate
new_rate.update!(selected: true)
end
end
|
#set_up_inventory(state, variant, _order, line_item) ⇒ Object
272
273
274
275
276
277
278
|
# File 'app/models/spree/shipment.rb', line 272
def set_up_inventory(state, variant, _order, line_item)
inventory_units.create(
state: state,
variant_id: variant.id,
line_item_id: line_item.id
)
end
|
#shipped=(value) ⇒ Object
280
281
282
283
|
# File 'app/models/spree/shipment.rb', line 280
def shipped=(value)
return unless value == '1' && shipped_at.nil?
self.shipped_at = Time.current
end
|
#shipping_method ⇒ Object
285
286
287
|
# File 'app/models/spree/shipment.rb', line 285
def shipping_method
selected_shipping_rate.try(:shipping_method)
end
|
#tax_total ⇒ Object
Only one of either included_tax_total or additional_tax_total is set This method returns the total of the two. Saves having to check if tax is included or additional.
292
293
294
|
# File 'app/models/spree/shipment.rb', line 292
def tax_total
included_tax_total + additional_tax_total
end
|
#to_package ⇒ Object
296
297
298
299
300
301
302
303
|
# File 'app/models/spree/shipment.rb', line 296
def to_package
package = Stock::Package.new(stock_location)
package.shipment = self
inventory_units.includes(:variant).joins(:variant).group_by(&:state).each do |state, state_inventory_units|
package.add_multiple state_inventory_units, state.to_sym
end
package
end
|
#to_param ⇒ Object
305
306
307
|
# File 'app/models/spree/shipment.rb', line 305
def to_param
number
end
|
#total ⇒ BigDecimal
Also known as:
final_price
Returns the amount of this shipment, taking into consideration all its adjustments.
136
137
138
|
# File 'app/models/spree/shipment.rb', line 136
def total
cost + adjustment_total
end
|
#total_before_tax ⇒ BigDecimal
Returns the amount of this item, taking into consideration all non-tax adjustments.
144
145
146
|
# File 'app/models/spree/shipment.rb', line 144
def total_before_tax
amount + adjustments.select { |a| !a.tax? && a.eligible? }.sum(&:amount)
end
|
#total_excluding_vat ⇒ BigDecimal
Also known as:
pre_tax_amount
Note:
just like ‘cost`, this does not include any additional tax
Returns the amount of this shipment before VAT tax.
150
151
152
|
# File 'app/models/spree/shipment.rb', line 150
def total_excluding_vat
total_before_tax - included_tax_total
end
|
#total_with_items ⇒ Object
Also known as:
final_price_with_items
156
157
158
|
# File 'app/models/spree/shipment.rb', line 156
def total_with_items
total + item_cost
end
|
#tracking_url ⇒ Object
309
310
311
312
313
|
# File 'app/models/spree/shipment.rb', line 309
def tracking_url
return nil unless tracking && shipping_method
@tracking_url ||= shipping_method.build_tracking_url(tracking)
end
|
#transfer_to_location(variant, quantity, stock_location) ⇒ Object
369
370
371
372
373
|
# File 'app/models/spree/shipment.rb', line 369
def transfer_to_location(variant, quantity, stock_location)
Spree::Deprecation.warn("Please use the Spree::FulfilmentChanger class instead of Spree::Shipment#transfer_to_location", caller)
new_shipment = order.shipments.create!(stock_location: stock_location)
transfer_to_shipment(variant, quantity, new_shipment)
end
|
#transfer_to_shipment(variant, quantity, shipment_to_transfer_to) ⇒ Object
375
376
377
378
379
380
381
382
383
|
# File 'app/models/spree/shipment.rb', line 375
def transfer_to_shipment(variant, quantity, shipment_to_transfer_to)
Spree::Deprecation.warn("Please use the Spree::FulfilmentChanger class instead of Spree::Shipment#transfer_to_location", caller)
Spree::FulfilmentChanger.new(
current_shipment: self,
desired_shipment: shipment_to_transfer_to,
variant: variant,
quantity: quantity
).run!
end
|
#update!(order_or_attrs) ⇒ Object
357
358
359
360
361
362
363
364
365
366
367
|
# File 'app/models/spree/shipment.rb', line 357
def update!(order_or_attrs)
if order_or_attrs.is_a?(Spree::Order)
Spree::Deprecation.warn "Calling Shipment#update! with an order to update the shipments state is deprecated. Please use Shipment#update_state instead."
if order_or_attrs.object_id != order.object_id
Spree::Deprecation.warn "Additionally, update! is being passed an instance of order which isn't the same object as the shipment's order association"
end
update_state
else
super
end
end
|
#update_amounts ⇒ Object
315
316
317
318
319
320
321
322
323
324
325
|
# File 'app/models/spree/shipment.rb', line 315
def update_amounts
if selected_shipping_rate
self.cost = selected_shipping_rate.cost
if changed?
update_columns(
cost: cost,
updated_at: Time.current
)
end
end
end
|
#update_attributes_and_order(params = {}) ⇒ Object
Update Shipment and make sure Order states follow the shipment changes
328
329
330
331
332
333
334
335
336
337
338
339
|
# File 'app/models/spree/shipment.rb', line 328
def update_attributes_and_order(params = {})
if update_attributes params
if params.key? :selected_shipping_rate_id
update_amounts
order.recalculate
end
true
end
end
|
#update_state ⇒ Object
Updates the state of the Shipment bypassing any callbacks.
If this moves the shipmnent to the ‘shipped’ state, after_ship will be called.
345
346
347
348
349
350
351
352
353
354
355
|
# File 'app/models/spree/shipment.rb', line 345
def update_state
old_state = state
new_state = determine_state(order)
if new_state != old_state
update_columns(
state: new_state,
updated_at: Time.current
)
after_ship if new_state == 'shipped'
end
end
|