app/models/bodega/order.rb in bodega-0.3.0 vs app/models/bodega/order.rb in bodega-0.4.0

- old
+ new

@@ -1,43 +1,145 @@ +require 'maintain' + module Bodega class Order < ActiveRecord::Base - before_save :set_total + self.table_name = :bodega_orders + + attr_accessible :order_products_attributes, :street_1, :street_2, :city, :state, :postal_code, :shipping_rate_code + before_create :set_identifier + before_save :set_shipping_rates, if: :postal_code_changed? + before_save :calculate_shipping, if: :shipping_rate_code_changed? + before_save :set_total belongs_to :customer, polymorphic: true + has_many :order_products, class_name: 'Bodega::OrderProduct', dependent: :destroy - has_many :products, through: :order_products + accepts_nested_attributes_for :order_products + delegate :empty?, to: :order_products + + maintain :status do + state :new, 1, default: true + state :complete, 2 + + on :enter, :complete, :mark_order_products_as_purchased + end + + monetize :shipping_cents monetize :tax_cents monetize :total_cents - def finalize!(payment_method) + serialize :shipping_rates + + def finalize!(options) self.class.transaction do + self.status = :complete self.save! begin - self.payment_id = payment_method.complete! - self.save! - rescue Exception => e + self.payment_id = payment_method.complete!(options) + self.save + rescue Exception raise ActiveRecord::Rollback - raise e.inspect end end end - def subtotal - @subtotal ||= order_products.inject(Money.new(0)) {|sum, order_product| sum += order_product.subtotal } + def payment_method + return nil unless Bodega.config.payment_method + @payment_method ||= "Bodega::PaymentMethod::#{Bodega.config.payment_method.to_s.camelize}".constantize.new(self) end - def set_total - self.total = subtotal + tax + def products + order_products.map(&:product) end + def ready? + shipping_method.present? || shipping_rates.any? + end + + def remove_product(item) + unless item.is_a?(Bodega::OrderProduct) + item = order_product(item) + end + item.destroy + order_products.delete(item) + end + + def shipping_method + case Bodega.config.shipping_method + when :ups + Bodega::ShippingMethod::UPS.new(self) + end + end + + def shipping_rate_options + @shipping_rate_options ||= ActiveSupport::OrderedHash.new.tap do |rates| + shipping_rates.sort_by {|code, rate| rate[:price] }.each do |code, rate| + name = rate[:name] + price = Money.new(rate[:price]) + rates["#{name}: #{price.format}"] = code + end + end + end + + def subtotal + order_products.inject(Money.new(0)) {|sum, order_product| sum += order_product.subtotal } + end + def to_param identifier end + def update_product(item) + if order_product = order_product(item) + if item[:remove] + remove_product(order_product) + else + current_quantity = order_product.quantity + new_quantity = item[:quantity] ? item[:quantity].to_i : current_quantity + 1 + order_product.update_attributes(quantity: new_quantity) + end + else + order_product = order_products.build({quantity: 1}.merge(item)) + end + save unless empty? + end + protected + def calculate_shipping + self.shipping = 0 + if shipping_rate_code + self.shipping_rate_name = shipping_rates[shipping_rate_code][:name] + self.shipping = shipping_rates[shipping_rate_code][:price] / 100.0 + end + end + + def calculate_tax + self.tax = 0 + end + + def mark_order_products_as_purchased + order_products.each(&:update_stock) + end + + def order_product(item) + if item.is_a?(Hash) + order_products.detect {|order_product| order_product.product_type == item[:product_type] && order_product.product_id == item[:product_id].to_i } + else + order_products.detect {|order_product| order_product.identifier == item } + end + end + def set_identifier self.identifier = self.class.count.succ.to_s(36) + end + + def set_shipping_rates + self.shipping_rates = postal_code.present? ? shipping_method.rates : nil + end + + def set_total + self.total = subtotal + tax + shipping end end end