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