Class: Spree::Shipment
- Inherits:
-
Base
- Object
- Base
- Spree::Shipment
- Extended by:
- DisplayMoney
- Includes:
- Metadata
- Defined in:
- app/models/spree/shipment.rb
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
- #after_cancel ⇒ Object
- #after_resume ⇒ Object
- #assign_amounts ⇒ 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
- #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
- #persist_amounts ⇒ Object
- #ready_or_pending? ⇒ Boolean
-
#recalculate_state ⇒ Object
Assigns the appropriate
stateaccording to the following logic:. - #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
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
The amount of this shipment before VAT tax.
- #total_with_items ⇒ Object
- #tracking_url ⇒ 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.
Methods included from DisplayMoney
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.
26 27 28 |
# File 'app/models/spree/shipment.rb', line 26 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.
26 27 28 |
# File 'app/models/spree/shipment.rb', line 26 def suppress_mailer @suppress_mailer end |
Instance Method Details
#after_cancel ⇒ Object
73 74 75 |
# File 'app/models/spree/shipment.rb', line 73 def after_cancel manifest.each { |item| manifest_restock(item) } end |
#after_resume ⇒ Object
77 78 79 |
# File 'app/models/spree/shipment.rb', line 77 def after_resume manifest.each { |item| manifest_unstock(item) } end |
#assign_amounts ⇒ Object
291 292 293 294 |
# File 'app/models/spree/shipment.rb', line 291 def assign_amounts return unless selected_shipping_rate self.cost = selected_shipping_rate.cost end |
#backordered? ⇒ Boolean
81 82 83 |
# File 'app/models/spree/shipment.rb', line 81 def backordered? inventory_units.any?(&:backordered?) end |
#can_transition_from_canceled_to_ready? ⇒ Boolean
61 62 63 |
# File 'app/models/spree/shipment.rb', line 61 def can_transition_from_canceled_to_ready? can_transition_from_pending_to_ready? end |
#can_transition_from_pending_to_ready? ⇒ Boolean
55 56 57 58 59 |
# File 'app/models/spree/shipment.rb', line 55 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
51 52 53 |
# File 'app/models/spree/shipment.rb', line 51 def can_transition_from_pending_to_shipped? !requires_shipment? end |
#currency ⇒ Object
85 86 87 |
# File 'app/models/spree/shipment.rb', line 85 def currency order ? order.currency : Spree::Config[:currency] end |
#determine_state(order) ⇒ Object
209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'app/models/spree/shipment.rb', line 209 def determine_state(order) Spree.deprecator.warn "Use Spree::Shipment#recalculate_state instead" return "shipped" if shipped? return "canceled" if order.canceled? || inventory_units.all?(&:canceled?) return "pending" unless order.can_ship? if can_transition_from_pending_to_ready? "ready" else "pending" end end |
#editable_by?(_user) ⇒ Boolean
111 112 113 |
# File 'app/models/spree/shipment.rb', line 111 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.
119 120 121 |
# File 'app/models/spree/shipment.rb', line 119 def finalize! finalize_pending_inventory_units end |
#include?(variant) ⇒ Boolean
123 124 125 |
# File 'app/models/spree/shipment.rb', line 123 def include?(variant) inventory_units_for(variant).present? end |
#inventory_units_for(variant) ⇒ Object
127 128 129 |
# File 'app/models/spree/shipment.rb', line 127 def inventory_units_for(variant) inventory_units.where(variant_id: variant.id) end |
#inventory_units_for_item(line_item, variant = nil) ⇒ Object
131 132 133 |
# File 'app/models/spree/shipment.rb', line 131 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
135 136 137 |
# File 'app/models/spree/shipment.rb', line 135 def item_cost line_items.sum(&:total) end |
#manifest ⇒ Object
180 181 182 183 184 185 186 187 |
# File 'app/models/spree/shipment.rb', line 180 def manifest @manifest ||= Spree::ShippingManifest.new( inventory_units:, # Only when it is already in memory — the manifest treats the order as an # optimization and must not cause a query for it. order: (order if association(:order).loaded?) ).items end |
#persist_amounts ⇒ Object
296 297 298 299 300 301 302 303 |
# File 'app/models/spree/shipment.rb', line 296 def persist_amounts if cost_changed? update_columns( cost:, updated_at: Time.current ) end end |
#ready_or_pending? ⇒ Boolean
139 140 141 |
# File 'app/models/spree/shipment.rb', line 139 def ready_or_pending? ready? || pending? end |
#recalculate_state ⇒ Object
Assigns 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
228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'app/models/spree/shipment.rb', line 228 def recalculate_state self.state = if shipped? "shipped" elsif order.canceled? || inventory_units.all?(&:canceled?) "canceled" elsif !order.can_ship? "pending" elsif can_transition_from_pending_to_ready? "ready" else "pending" end end |
#refresh_rates ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'app/models/spree/shipment.rb', line 143 def refresh_rates return shipping_rates if shipped? return [] unless can_get_rates? # StockEstimator.new assigment below will replace the current shipping_method original_shipping_method_id = shipping_method.try!(:id) new_rates = Spree::Config.stock.estimator_class.new.shipping_rates(to_package) # If one of the new rates matches the previously selected shipping # method, select that instead of the default provided by the estimator. # Otherwise, keep the default. 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
332 333 334 |
# File 'app/models/spree/shipment.rb', line 332 def requires_shipment? !stock_location || stock_location.fulfillable? end |
#select_shipping_method(shipping_method) ⇒ Object
168 169 170 171 172 173 174 |
# File 'app/models/spree/shipment.rb', line 168 def select_shipping_method(shipping_method) estimator = Spree::Config.stock.estimator_class.new rates = estimator.shipping_rates(to_package, false) rate = rates.detect { |detected| detected.shipping_method_id == shipping_method.id } rate.selected = true self.shipping_rates = [rate] end |
#selected_shipping_rate ⇒ Object
176 177 178 |
# File 'app/models/spree/shipment.rb', line 176 def selected_shipping_rate shipping_rates.detect(&:selected?) end |
#selected_shipping_rate_id ⇒ Object
189 190 191 |
# File 'app/models/spree/shipment.rb', line 189 def selected_shipping_rate_id selected_shipping_rate.try(:id) end |
#selected_shipping_rate_id=(id) ⇒ Object
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'app/models/spree/shipment.rb', line 193 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) new_rate.update!(selected: true) end end |
#set_up_inventory(state, variant, _order, line_item) ⇒ Object
243 244 245 246 247 248 249 |
# File 'app/models/spree/shipment.rb', line 243 def set_up_inventory(state, variant, _order, line_item) inventory_units.create( state:, variant_id: variant.id, line_item_id: line_item.id ) end |
#shipped=(value) ⇒ Object
251 252 253 254 |
# File 'app/models/spree/shipment.rb', line 251 def shipped=(value) return unless value == "1" && shipped_at.nil? self.shipped_at = Time.current end |
#shipping_method ⇒ Object
256 257 258 |
# File 'app/models/spree/shipment.rb', line 256 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.
263 264 265 |
# File 'app/models/spree/shipment.rb', line 263 def tax_total included_tax_total + additional_tax_total end |
#to_package ⇒ Object
267 268 269 270 271 272 273 274 |
# File 'app/models/spree/shipment.rb', line 267 def to_package package = Stock::Package.new(stock_location) package.shipment = self inventory_units.includes(variant: :product).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
276 277 278 |
# File 'app/models/spree/shipment.rb', line 276 def to_param number end |
#total ⇒ BigDecimal
91 92 93 |
# File 'app/models/spree/shipment.rb', line 91 def total cost + adjustment_total end |
#total_before_tax ⇒ BigDecimal
97 98 99 |
# File 'app/models/spree/shipment.rb', line 97 def total_before_tax amount + adjustments.reject { |adjustment| adjustment.tax? || adjustment.marked_for_destruction? }.sum(&:amount) end |
#total_excluding_vat ⇒ BigDecimal
just like cost, this does not include any additional tax
Returns the amount of this shipment before VAT tax.
103 104 105 |
# File 'app/models/spree/shipment.rb', line 103 def total_excluding_vat total_before_tax - included_tax_total end |
#total_with_items ⇒ Object
107 108 109 |
# File 'app/models/spree/shipment.rb', line 107 def total_with_items total + item_cost end |
#tracking_url ⇒ Object
280 281 282 283 284 |
# File 'app/models/spree/shipment.rb', line 280 def tracking_url return nil unless tracking && shipping_method @tracking_url ||= shipping_method.build_tracking_url(tracking) end |
#update_amounts ⇒ Object
286 287 288 289 |
# File 'app/models/spree/shipment.rb', line 286 def update_amounts assign_amounts persist_amounts end |
#update_attributes_and_order(params = {}) ⇒ Object
Update Shipment and make sure Order states follow the shipment changes
306 307 308 309 310 311 312 313 314 315 316 317 |
# File 'app/models/spree/shipment.rb', line 306 def update_attributes_and_order(params = {}) if update(params) if params.key? :selected_shipping_rate_id # Changing the selected Shipping Rate won't update the cost (for now) # so we persist the Shipment#cost before running `order.recalculate` update_amounts order.recalculate end true end end |
#update_state ⇒ Object
Updates the state of the Shipment bypassing any callbacks.
If this moves the shipment to the 'shipped' state, after_ship will be called.
323 324 325 326 327 328 329 330 |
# File 'app/models/spree/shipment.rb', line 323 def update_state old_state = state new_state = recalculate_state if new_state != old_state update_columns state: new_state, updated_at: Time.current after_ship if new_state == "shipped" end end |