Class: Tienda::OrderItem

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/tienda/order_item.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.add_item(ordered_item, quantity = 1) ⇒ Tienda::OrderItem

This allows you to add a product to the scoped order. For example Order.first.order_items.add_product(…). This will either increase the quantity of the value in the order or create a new item if one does not exist already.

Parameters:

  • ordered_item (Object)

    an object which implements the Tienda::OrderableItem protocol

  • quantity (Fixnum) (defaults to: 1)

    the number of items to order

Returns:

Raises:



48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'app/models/tienda/order_item.rb', line 48

def self.add_item(ordered_item, quantity = 1)
  raise Errors::UnorderableItem, ordered_item: ordered_item unless ordered_item.orderable?
  transaction do
    if existing = self.where(ordered_item_id: ordered_item.id, ordered_item_type: ordered_item.class.to_s).first
      existing.increase!(quantity)
      existing
    else
      new_item = self.create(ordered_item: ordered_item, quantity: 0)
      new_item.increase!(quantity)
      new_item
    end
  end
end

Instance Method Details

#accept!Object

Trigger when the associated order is accepted



185
186
# File 'app/models/tienda/order_item.rb', line 185

def accept!
end

#allocate_unallocated_stock!Object

Allocate any unallocated stock for this order item. There is no return value.



232
233
234
235
236
# File 'app/models/tienda/order_item.rb', line 232

def allocate_unallocated_stock!
  if self.ordered_item.stock_control? && self.unallocated_stock != 0
    self.ordered_item.stock_level_adjustments.create!(parent: self, adjustment: 0 - self.unallocated_stock, description: "Order ##{self.order.number}")
  end
end

#allocated_stockFixnum

How much stock has been allocated to this item?

Returns:

  • (Fixnum)


214
215
216
# File 'app/models/tienda/order_item.rb', line 214

def allocated_stock
  0 - self.stock_level_adjustments.sum(:adjustment)
end

#cache_pricingObject

Cache the pricing for this order item



164
165
166
167
168
169
# File 'app/models/tienda/order_item.rb', line 164

def cache_pricing
  write_attribute :weight, self.weight
  write_attribute :unit_price, self.unit_price
  write_attribute :unit_cost_price, self.unit_cost_price
  write_attribute :tax_rate, self.tax_rate
end

#cache_pricing!Object

Cache the pricing for this order item and save



172
173
174
175
# File 'app/models/tienda/order_item.rb', line 172

def cache_pricing!
  cache_pricing
  save!
end

#confirm!Object

Trigger when the associated order is confirmed. It handles caching the values of the monetary items and allocating stock as appropriate.



179
180
181
182
# File 'app/models/tienda/order_item.rb', line 179

def confirm!
  cache_pricing!
  allocate_unallocated_stock!
end

#decrease!(amount = 1) ⇒ Object

Decreases the quantity of items in the order by the number provided.

Parameters:

  • amount (Fixnum) (defaults to: 1)


92
93
94
95
96
97
98
# File 'app/models/tienda/order_item.rb', line 92

def decrease!(amount = 1)
  transaction do
    self.quantity -= amount
    self.quantity == 0 ? self.destroy : self.save!
    self.order.remove_delivery_service_if_invalid
  end
end

#in_stock?Boolean

Do we have the stock needed to fulfil this order?

Returns:

  • (Boolean)


196
197
198
199
200
201
202
# File 'app/models/tienda/order_item.rb', line 196

def in_stock?
  if self.ordered_item && self.ordered_item.stock_control?
    self.ordered_item.stock_count >= unallocated_stock
  else
    true
  end
end

#increase!(amount = 1) ⇒ Object

Increases the quantity of items in the order by the number provided. Will raise an error if we don’t have the stock to do this.

Parameters:

  • quantity (Fixnum)


78
79
80
81
82
83
84
85
86
87
# File 'app/models/tienda/order_item.rb', line 78

def increase!(amount = 1)
  transaction do
    self.quantity += amount
    unless self.in_stock?
      raise Tienda::Errors::NotEnoughStock, ordered_item: self.ordered_item, requested_stock: self.quantity
    end
    self.save!
    self.order.remove_delivery_service_if_invalid
  end
end

#orderTienda::Order

The associated order

Returns:



9
# File 'app/models/tienda/order_item.rb', line 9

belongs_to :order, class_name: 'Tienda::Order', touch: true

#reject!Object

Trigged when the associated order is rejected..



189
190
191
# File 'app/models/tienda/order_item.rb', line 189

def reject!
  self.stock_level_adjustments.destroy_all
end

#removeTienda::OrderItem

Remove a product from an order. It will also ensure that the order’s custom delivery service is updated if appropriate.

Returns:



66
67
68
69
70
71
72
# File 'app/models/tienda/order_item.rb', line 66

def remove
  transaction do
    self.destroy!
    self.order.remove_delivery_service_if_invalid
    self
  end
end

#sub_totalBigDecimal

The sub total for the product

Returns:

  • (BigDecimal)


152
153
154
# File 'app/models/tienda/order_item.rb', line 152

def sub_total
  quantity * unit_price
end

#tax_amountBigDecimal

The total tax for the item

Returns:

  • (BigDecimal)


138
139
140
# File 'app/models/tienda/order_item.rb', line 138

def tax_amount
  read_attribute(:tax_amount) || (self.sub_total / BigDecimal(100)) * self.tax_rate
end

#tax_rateBigDecimal

The tax rate for the item

Returns:

  • (BigDecimal)


131
132
133
# File 'app/models/tienda/order_item.rb', line 131

def tax_rate
  read_attribute(:tax_rate) || ordered_item.try(:tax_rate).try(:rate_for, self.order) || BigDecimal(0)
end

#totalBigDecimal

The total price including tax for the order line

Returns:

  • (BigDecimal)


159
160
161
# File 'app/models/tienda/order_item.rb', line 159

def total
  tax_amount + sub_total
end

#total_costBigDecimal

The total cost for the product

Returns:

  • (BigDecimal)


145
146
147
# File 'app/models/tienda/order_item.rb', line 145

def total_cost
  quantity * unit_cost_price
end

#total_weightBigDecimal

Return the total weight of the item

Returns:

  • (BigDecimal)


110
111
112
# File 'app/models/tienda/order_item.rb', line 110

def total_weight
  quantity * weight
end

#unallocated_stockFixnum

How much stock remains to be allocated for this order?

Returns:

  • (Fixnum)


207
208
209
# File 'app/models/tienda/order_item.rb', line 207

def unallocated_stock
  self.quantity - allocated_stock
end

#unit_cost_priceBigDecimal

The cost price for the item

Returns:

  • (BigDecimal)


124
125
126
# File 'app/models/tienda/order_item.rb', line 124

def unit_cost_price
  read_attribute(:unit_cost_price) || ordered_item.try(:cost_price) || BigDecimal(0)
end

#unit_priceBigDecimal

The unit price for the item

Returns:

  • (BigDecimal)


117
118
119
# File 'app/models/tienda/order_item.rb', line 117

def unit_price
  read_attribute(:unit_price) || ordered_item.try(:price) || BigDecimal(0)
end

#validate_stock_levelsObject

Validate the stock level against the product and update as appropriate. This method will be executed before an order is completed. If we have run out of this product, we will update the quantity to an appropriate level (or remove the order item) and return the object.



221
222
223
224
225
226
227
228
229
# File 'app/models/tienda/order_item.rb', line 221

def validate_stock_levels
  if in_stock?
    false
  else
    self.quantity = self.ordered_item.stock
    self.quantity == 0 ? self.destroy : self.save!
    self
  end
end

#weightBigDecimal

The total weight of the item

Returns:

  • (BigDecimal)


103
104
105
# File 'app/models/tienda/order_item.rb', line 103

def weight
  read_attribute(:weight) || ordered_item.try(:weight) || BigDecimal(0)
end