Class: Order

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
AASM, ActiveMerchant::Billing, ActiveMerchant::Shipping
Defined in:
lib/forge/app/models/order.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#shipping_ratesObject

Returns the value of attribute shipping_rates.



25
26
27
# File 'lib/forge/app/models/order.rb', line 25

def shipping_rates
  @shipping_rates
end

Class Method Details

.capture_payment(raw_post) ⇒ Object

for capturing PayPal notifications



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/forge/app/models/order.rb', line 204

def self.capture_payment(raw_post)
  notify = Paypal::Notification.new(raw_post)
  MySettings.paypal_invoice_prefix.empty? ? invoice_num = notify.invoice : invoice_num = notify.invoice.gsub(MySettings.paypal_invoice_prefix, "")
  order = Order.find(invoice_num)
  if order
    if notify.acknowledge
      begin
        if notify.complete?
          order.pay!
        else
          order.fail!
        end
      rescue => e
        order.fail!
      end
    end
    order.save
    order
  end
end

Instance Method Details

#add(product, quantity = 1) ⇒ Object



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/forge/app/models/order.rb', line 170

def add(product, quantity = 1)
  quantity = quantity.to_i
  if quantity < 1
    self.line_items.delete(self.line_items.find_by_product_id(product.id))
  else
    if product.published?
      if !self.products.include?(product)
        li = LineItem.new(:quantity => quantity)
        li.product_id = product.id # product is protected against mass assignment
        li.price = product.price # price is protected against mass assignment
        self.line_items << li
      else
        li = self.line_items.find_by_product_id(product.id)
        li.quantity += quantity
        li.save
      end
    end
  end
end

#authorization_referenceObject



253
254
255
256
257
258
259
# File 'lib/forge/app/models/order.rb', line 253

def authorization_reference
  if authorization = transactions.find_by_action_and_success('authorization', true, :order => 'id ASC')
    authorization.reference
  else
    nil
  end
end

#authorize_payment(credit_card, options = {}) ⇒ Object

TODO: should total_price be multiplied by 100 to be in cents?



226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/forge/app/models/order.rb', line 226

def authorize_payment(credit_card, options = {})
  options[:order_id] = self.id
  transaction do
    authorization = OrderTransaction.authorize(total_price_in_cents, credit_card, options)
    transactions.push(authorization)
    if authorization.success?
      authorize!
    else
      fail!
    end
    authorization
  end
end

#can_calculate_shipping?Boolean

whether or not the order can currently calculate shipping

Returns:

  • (Boolean)


154
155
156
# File 'lib/forge/app/models/order.rb', line 154

def can_calculate_shipping?
  !self.shipping_address.blank? && self.shipping_address.valid?
end

#can_calculate_tax?Boolean

Returns:

  • (Boolean)


158
159
160
# File 'lib/forge/app/models/order.rb', line 158

def can_calculate_tax?
  !self.billing_address.blank? && self.billing_address.valid?
end

#capture_payment(options = {}) ⇒ Object



240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/forge/app/models/order.rb', line 240

def capture_payment(options = {})
  transaction do
    capture = OrderTransaction.capture(total_price_in_cents, authorization_reference, options)
    transactions.push(capture)
    if capture.success?
      pay!
    else
      fail!
    end
    capture
  end
end

#create_key!Object



190
191
192
193
194
195
196
197
# File 'lib/forge/app/models/order.rb', line 190

def create_key!
  self.key = generate_key
  until Order.find_by_key(self.key).nil?
    self.key = generate_key
  end
  self.save!
  self.key
end

#discountObject

TODO: make this work



83
84
85
# File 'lib/forge/app/models/order.rb', line 83

def discount
  0
end

#handlingObject



162
163
164
# File 'lib/forge/app/models/order.rb', line 162

def handling
  MySettings.handling.to_f || 0
end

#invoice_idObject



53
54
55
56
57
# File 'lib/forge/app/models/order.rb', line 53

def invoice_id
  invoice = MySettings.paypal_invoice_prefix.blank? ? "" : MySettings.paypal_invoice_prefix
  invoice += id.to_s
  return invoice
end

#priceObject



59
60
61
62
63
# File 'lib/forge/app/models/order.rb', line 59

def price
  self.line_items.inject(0.0) { |sum, line_item| sum + line_item.total_price }
rescue NoMethodError
  nil
end

#price_with_taxObject



65
66
67
# File 'lib/forge/app/models/order.rb', line 65

def price_with_tax
  price + tax
end

#shippingObject



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/forge/app/models/order.rb', line 87

def shipping
  amount = 0.0
  # raise "A valid shipping address must exist in order to calculate the shipping" if self.shipping_address.blank? || !self.shipping_address.valid?
  if Forge.config.ecommerce.flat_rate_shipping
    amount = self.line_items.inject(0.0) { |sum, line_item| sum += (line_item.quantity * line_item.product.flat_rate_shipping) }
  elsif self.shipping_cost
    amount = self.shipping_cost
  else
    @shipping_rates = shipping_quote if @shipping_rate.nil?
    amount = @shipping_rates[0][:price] unless @shipping_rates.nil?
    self.shipping_cost = amount
    self.save
  end
  amount
end

#shipping_and_handlingObject



166
167
168
# File 'lib/forge/app/models/order.rb', line 166

def shipping_and_handling
  shipping + handling
end

#shipping_quoteObject

OPTIMIZE: this method is excessively long and could be decomposed into several other methods



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/forge/app/models/order.rb', line 104

def shipping_quote
  shipper = MySettings.shipper
  if !shipper.blank?
    # Create packages array containing a package of each order item. (What to do with multiples of the same item?)
    packages = []
    self.line_items.each do |item|
      product = item.product
      for i in (1..item.quantity)
        packages.push( Package.new(
            product.weight,
            [product.width, product.height, product.depth],
            :value => product.price
          )
        )
      end
    end

    # Set up Origin and Destination
    origin = Location.new(
      :country => MySettings.origin_country,
      :province => MySettings.origin_province,
      :city => MySettings.origin_city,
      :postal_code => MySettings.origin_postal
    )
    add = self.shipping_address
    destination = Location.new(
      :country => add.country.code,
      :province => add.province.title,
      :city => add.city,
      :postal_code => add.postal
    )

    # Run functions to get cost estimates
    shipper = "ActiveMerchant::Shipping::#{MySettings.shipper.underscore.parameterize('_').camelize}".constantize.new(Forge.config.ecommers.shippers[MySettings.shipper.underscore.parameterize("_").to_sym])
    begin
      response = shipper.find_rates(origin, destination, packages)
      # Store all rates, order by price. Return cheapest rate.
      rates = response.rates.sort_by(&:price).collect {|rate| {:service => rate.service_name, :price => rate.price/100.0}}
    rescue ActiveMerchant::Shipping::ResponseError => e
      # Error response
      rates = nil
    end
  else
    #No shipper has been defined
  end

  return rates
end

#taxObject



77
78
79
80
# File 'lib/forge/app/models/order.rb', line 77

def tax
  # raise "A valid billing address must exist in order to calculate the tax" if self.billing_address.blank? || !self.billing_address.valid?
  self.line_items.inject(0.0) { |sum, line_item| sum += line_item.total_tax(self.billing_address) }
end

#total_priceObject



69
70
71
# File 'lib/forge/app/models/order.rb', line 69

def total_price
  (price_with_tax + shipping + handling) - discount
end

#total_price_in_centsObject



73
74
75
# File 'lib/forge/app/models/order.rb', line 73

def total_price_in_cents
  (total_price * 100.0).to_i
end

#valid_addresses?Boolean

Returns:

  • (Boolean)


199
200
201
# File 'lib/forge/app/models/order.rb', line 199

def valid_addresses?
  self.billing_address && self.billing_address.valid? && self.shipping_address && self.shipping_address.valid?
end