app/models/comable/order.rb in comable-0.0.2 vs app/models/comable/order.rb in comable-0.0.3
- old
+ new
@@ -1,29 +1,93 @@
module Comable
class Order < ActiveRecord::Base
include Decoratable
belongs_to :customer, class_name: Comable::Customer.name, foreign_key: Comable::Customer.table_name.singularize.foreign_key, autosave: false
+ belongs_to :payment, class_name: Comable::Payment.name, foreign_key: Comable::Payment.table_name.singularize.foreign_key, autosave: false
has_many :order_deliveries, dependent: :destroy, class_name: Comable::OrderDelivery.name, foreign_key: table_name.singularize.foreign_key
accepts_nested_attributes_for :order_deliveries
- validates :family_name, presence: true
- validates :first_name, presence: true
+ with_options if: :complete? do |complete_order|
+ complete_order.validates :code, presence: true
+ complete_order.validates :first_name, presence: true
+ complete_order.validates :family_name, presence: true
+ complete_order.validates Comable::Payment.table_name.singularize.foreign_key, presence: true
+ end
- before_create :generate_code
- before_create :generate_ordered_at
+ with_options if: :incomplete? do |incomplete_order|
+ incomplete_order.validates Comable::Customer.table_name.singularize.foreign_key, uniqueness: { scope: [Comable::Customer.table_name.singularize.foreign_key, :completed_at] }, if: :customer
+ incomplete_order.validates :guest_token, uniqueness: { scope: [:guest_token, :completed_at] }, if: :guest_token
+ end
+ before_create :generate_guest_token
+
+ scope :complete, -> { where.not(completed_at: nil) }
+ scope :incomplete, -> { where(completed_at: nil) }
+
+ def precomplete
+ valid_stock
+ fail Comable::InvalidOrder, errors.full_messages.join("\n") if errors.any?
+ self
+ end
+
+ def complete
+ # TODO: トランザクションの追加
+ precomplete
+ # TODO: コールバック化
+ # define_model_callbacks :complete
+ before_complete
+ save!
+ self
+ end
+
+ def complete?
+ !incomplete?
+ end
+
+ def incomplete?
+ completed_at.nil?
+ end
+
+ # 時価合計を取得
+ def current_total_price
+ order_deliveries.map(&:order_details).flatten.each(&:current_subtotal_price)
+ end
+
+ # 売価合計を取得
+ def total_price
+ order_deliveries.map(&:order_details).flatten.each(&:subtotal_price)
+ end
+
private
+ def before_complete
+ self.completed_at = Time.now
+ generate_code
+ order_deliveries.each(&:before_complete)
+ end
+
+ def valid_stock
+ order_deliveries.map(&:order_details).flatten.each do |order_detail|
+ return errors.add :base, "「#{order_detail.stock.name}」の注文数が不正です。" if order_detail.quantity <= 0
+ quantity = order_detail.stock.quantity - order_detail.quantity
+ return errors.add :base, "「#{order_detail.stock.name}」の在庫が不足しています。" if quantity < 0
+ end
+ end
+
def generate_code
self.code = loop do
random_token = "C#{Array.new(11) { rand(9) }.join}"
break random_token unless self.class.exists?(code: random_token)
end
end
- def generate_ordered_at
- self.ordered_at = Time.now
+ def generate_guest_token
+ return if send(Comable::Customer.table_name.singularize.foreign_key)
+ self.guest_token ||= loop do
+ random_token = SecureRandom.urlsafe_base64(nil, false)
+ break random_token unless self.class.exists?(guest_token: random_token)
+ end
end
end
end