Class: Spree::LineItem

Inherits:
Object
  • Object
show all
Extended by:
DisplayMoney
Includes:
Metadata, Metafields
Defined in:
app/models/spree/line_item.rb

Constant Summary collapse

DB_INTEGER_MAX =
(2**31) - 1

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from DisplayMoney

money_methods

Methods included from Metadata

#metadata, #metadata=, #public_metadata=

Instance Attribute Details

#target_shipmentObject

Returns the value of attribute target_shipment.



69
70
71
# File 'app/models/spree/line_item.rb', line 69

def target_shipment
  @target_shipment
end

Instance Method Details

#amountBigDecimal Also known as: subtotal

Returns the amount (price * quantity) of the line item

Returns:

  • (BigDecimal)


119
120
121
# File 'app/models/spree/line_item.rb', line 119

def amount
  price * quantity
end

#any_shipped?Boolean

returns true if any of the inventory units are shipped

Returns:



210
211
212
# File 'app/models/spree/line_item.rb', line 210

def any_shipped?
  inventory_units.any?(&:shipped?)
end

#compare_at_amountBigDecimal

Returns the compare at amount (compare at price * quantity) of the line item

Returns:

  • (BigDecimal)


126
127
128
# File 'app/models/spree/line_item.rb', line 126

def compare_at_amount
  (variant.compare_at_amount_in(currency) || 0) * quantity
end

#copy_priceObject



78
79
80
81
82
83
84
# File 'app/models/spree/line_item.rb', line 78

def copy_price
  if variant
    update_price if price.nil?
    self.cost_price = variant.cost_price if cost_price.nil?
    self.currency = order.currency if currency.nil?
  end
end

#copy_tax_categoryObject



94
95
96
# File 'app/models/spree/line_item.rb', line 94

def copy_tax_category
  self.tax_category = variant.tax_category if variant
end

#discounted_priceObject



110
111
112
113
114
# File 'app/models/spree/line_item.rb', line 110

def discounted_price
  return price if quantity.zero?

  price - (promo_total.abs / quantity)
end

#final_amountBigDecimal Also known as: total

Returns the final amount of the line item

Returns:

  • (BigDecimal)


175
176
177
# File 'app/models/spree/line_item.rb', line 175

def final_amount
  amount + adjustment_total
end

#fully_shipped?Boolean

returns true if all of the inventory units are shipped

Returns:



217
218
219
# File 'app/models/spree/line_item.rb', line 217

def fully_shipped?
  inventory_units.all?(&:shipped?)
end

#insufficient_stock?Boolean

Returns true if the line item has insufficient stock

Returns:



203
204
205
# File 'app/models/spree/line_item.rb', line 203

def insufficient_stock?
  !sufficient_stock?
end

#item_weightBigDecimal

Returns the weight of the line item

Returns:

  • (BigDecimal)


182
183
184
# File 'app/models/spree/line_item.rb', line 182

def item_weight
  variant.weight * quantity
end

#maximum_quantityInteger

Returns the maximum quantity that can be added to the line item

Returns:

  • (Integer)


262
263
264
# File 'app/models/spree/line_item.rb', line 262

def maximum_quantity
  @maximum_quantity ||= variant.backorderable? ? DB_INTEGER_MAX : variant.total_on_hand
end

#options=(options = {}) ⇒ Object



248
249
250
251
252
253
254
255
256
257
# File 'app/models/spree/line_item.rb', line 248

def options=(options = {})
  return unless options.present?

  opts = options.dup # we will be deleting from the hash, so leave the caller's copy intact

  currency = opts.delete(:currency) || order.try(:currency)

  update_price_from_modifier(currency, opts)
  assign_attributes opts
end

#recalculate_pricevoid

This method returns an undefined value.

Recalculates and persists the price based on the current quantity and pricing context This is used for volume-based pricing and other price list rules



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'app/models/spree/line_item.rb', line 276

def recalculate_price
  context = Spree::Pricing::Context.from_order(variant, order, quantity: quantity)
  currency_price = variant.price_for(context)

  return unless currency_price.present?

  new_price = currency_price.price_including_vat_for(tax_zone: tax_zone)

  return unless new_price.present?

  new_price_list_id = currency_price.price_list_id

  # Only update if price or price list changed
  if new_price != price || new_price_list_id != price_list_id
    update_columns(price: new_price, price_list_id: new_price_list_id, updated_at: Time.current)
  end
end

#shipping_costBigDecimal

Returns the shipping cost for the line item

Returns:

  • (BigDecimal)


224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'app/models/spree/line_item.rb', line 224

def shipping_cost
  shipments.sum do |shipment|
    # Skip cancelled shipments
    return BigDecimal('0') if shipment.canceled?

    # Skip shipments with no cost/zero cost
    return BigDecimal('0') if shipment.cost.zero?

    # Get total inventory units in this shipment
    total_units = shipment.inventory_units

    # Calculate proportional shipping cost
    return BigDecimal('0') if total_units.empty?

    # Get all inventory units in this shipment for this line item
    line_item_units = shipment.inventory_units.find_all { |unit| unit.line_item_id == id }.count

    # Calculate proportional shipping cost
    return BigDecimal('0') if line_item_units.zero?

    shipment.cost * (line_item_units.to_d / total_units.count)
  end
end

#sufficient_stock?Boolean

Returns true if the line item has sufficient stock

The order's own active stock reservations are excluded from the availability check — a customer's own checkout hold must not make their own line item look out of stock.

Returns:



196
197
198
# File 'app/models/spree/line_item.rb', line 196

def sufficient_stock?
  Spree::Stock::Quantifier.new(variant, excluded_order: order).can_supply?(quantity)
end

#tax_totalBigDecimal

returns the total tax amount

Returns:

  • (BigDecimal)


142
143
144
# File 'app/models/spree/line_item.rb', line 142

def tax_total
  included_tax_total + additional_tax_total
end

#taxable_amountBigDecimal Also known as: discounted_amount

Returns the taxable amount (amount + taxable adjustment total) of the line item

Returns:

  • (BigDecimal)


135
136
137
# File 'app/models/spree/line_item.rb', line 135

def taxable_amount
  amount + taxable_adjustment_total
end

#taxable_basisBigDecimal

Returns the amount this line item is taxed on: the discounted amount reduced further by the line item's proportional share of any whole-order promotions, which are adjustments on the order itself and therefore not part of taxable_adjustment_total. Never negative.

Returns:

  • (BigDecimal)


155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'app/models/spree/line_item.rb', line 155

def taxable_basis
  basis = taxable_amount
  return basis if basis <= 0

  order_discount = order.order_level_promo_total
  return basis if order_discount.zero?

  # summed in SQL so the allocation uses the persisted adjustment totals
  # of all line items, not a possibly stale cached association
  items_total = order.line_items.reorder(nil).pick(
    Arel.sql('COALESCE(SUM(price * quantity + taxable_adjustment_total), 0)')
  )
  return basis if items_total <= 0

  [basis + (order_discount * basis / items_total), BigDecimal(0)].max
end

#thumbnailSpree::Asset?

Returns the thumbnail image for this line item Prefers variant primary media, falls back to product primary media

Returns:



61
62
63
# File 'app/models/spree/line_item.rb', line 61

def thumbnail
  variant.primary_media || product.primary_media
end

#update_priceObject



86
87
88
89
90
91
92
# File 'app/models/spree/line_item.rb', line 86

def update_price
  context = Spree::Pricing::Context.from_order(variant, order, quantity: quantity)
  currency_price = variant.price_for(context)

  self.price = currency_price.price_including_vat_for(tax_zone: tax_zone) if currency_price.present?
  self.price_list_id = currency_price.price_list_id if currency_price.present?
end

#with_digital_assets?Boolean

Returns true if the line item variant has digital assets

Returns:



269
270
271
# File 'app/models/spree/line_item.rb', line 269

def with_digital_assets?
  variant.with_digital_assets?
end