Class: Shoppe::OrderItem

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

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.add_item(ordered_item, quantity = 1) ⇒ Shoppe::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 Shoppe::OrderableItem protocol

  • quantity (Fixnum) (defaults to: 1)

    the number of items to order

Returns:

Raises:



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'app/models/shoppe/order_item.rb', line 30

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



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

def accept!
end

#confirm!Object

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



134
135
136
137
138
139
140
141
142
143
# File 'app/models/shoppe/order_item.rb', line 134

def confirm!
  write_attribute :unit_price, self.unit_price
  write_attribute :unit_cost_price, self.unit_cost_price
  write_attribute :tax_rate, self.tax_rate
  write_attribute :tax_amount, self.tax_amount
  save!
  if self.ordered_item.stock_control?
    self.ordered_item.stock_level_adjustments.create(:parent => self, :adjustment => 0 - self.quantity, :description => "Order ##{self.order.number} deduction")
  end
end

#decrease!(amount = 1) ⇒ Object

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

Parameters:

  • amount (Fixnum) (defaults to: 1)


75
76
77
78
79
80
81
# File 'app/models/shoppe/order_item.rb', line 75

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)


157
158
159
160
161
162
163
# File 'app/models/shoppe/order_item.rb', line 157

def in_stock?
  if self.ordered_item.stock_control?
    self.ordered_item.stock >= self.quantity
  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)


61
62
63
64
65
66
67
68
69
70
# File 'app/models/shoppe/order_item.rb', line 61

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

#orderShoppe::Order

The associated order

Returns:



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

belongs_to :order, :class_name => 'Shoppe::Order'

#reject!Object

Trigged when the associated order is rejected..



150
151
152
# File 'app/models/shoppe/order_item.rb', line 150

def reject!
  self.stock_level_adjustments.destroy_all
end

#removeShoppe::OrderItem

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

Returns:



48
49
50
51
52
53
54
# File 'app/models/shoppe/order_item.rb', line 48

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)


121
122
123
# File 'app/models/shoppe/order_item.rb', line 121

def sub_total
  quantity * unit_price
end

#tax_amountBigDecimal

The total tax for the item

Returns:

  • (BigDecimal)


107
108
109
# File 'app/models/shoppe/order_item.rb', line 107

def tax_amount
  @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)


100
101
102
# File 'app/models/shoppe/order_item.rb', line 100

def tax_rate
  @tax_rate ||= read_attribute(:tax_rate) || ordered_item.try(:tax_rate).try(:rate_for, self.order) || 0.0 
end

#totalBigDecimal

The total price including tax for the order line

Returns:

  • (BigDecimal)


128
129
130
# File 'app/models/shoppe/order_item.rb', line 128

def total
  tax_amount + sub_total
end

#total_costBigDecimal

The total cost for the product

Returns:

  • (BigDecimal)


114
115
116
# File 'app/models/shoppe/order_item.rb', line 114

def total_cost
  quantity * unit_cost_price
end

#unit_cost_priceBigDecimal

The cost price for the item

Returns:

  • (BigDecimal)


93
94
95
# File 'app/models/shoppe/order_item.rb', line 93

def unit_cost_price
  @unit_cost_price ||= read_attribute(:unit_cost_price) || ordered_item.try(:cost_price) || 0.0
end

#unit_priceBigDecimal

The unit price for the item

Returns:

  • (BigDecimal)


86
87
88
# File 'app/models/shoppe/order_item.rb', line 86

def unit_price
  @unit_price ||= read_attribute(:unit_price) || ordered_item.try(:price) || 0.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.



168
169
170
171
172
173
174
175
176
# File 'app/models/shoppe/order_item.rb', line 168

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