每30天仅限3个订单

时间:2016-06-23 21:00:28

标签: ruby-on-rails model-view-controller

我正在Rails中建立一个具有特定销售模型的商店。我需要允许用户每30天只创建3个订单。因此,如果用户创建一个订单,那么在30天内允许另外两个订单。 30天柜台应该在创建第一个订单时开始。 30天后重置计数器进行订购,用户再次能够创建3个订单......

现在,一旦创建了每个订单,它就会保存到数据库中,并且可以获得无限量的订单。

我不确定如何实现这一目标并限制current_user每30天创建超过3个订单。 我还想显示一个错误通知,即每30天不可能超过3个订单。

我有产品,订单,用户,每个都有模型和控制器。订单也能够具有许多状态,如“已完成”,“处理”等。 我正在使用标准的Devise身份验证。

order_items_controller:

def create
    @order = current_order
    @order_item = @order.order_items.new(order_item_params)
    @order.user_id = current_user.id
    @order.save
    session[:order_id] = @order.id

  respond_to do |format|
    format.js { flash[:notice] = "ORDER HAS BEEN CREATED." } 
  end
  end
private
  def order_item_params
    params.require(:order_item).permit(:quantity, :product_id, :user_id)
  end
end

Order.rb

class Order < ActiveRecord::Base
  belongs_to :order_status
  has_many :order_items
  before_create :set_order_status
  before_save :update_subtotal

  def subtotal
    order_items.collect { |oi| oi.valid? ? (oi.quantity * oi.unit_price) : 0 }.sum
  end
private
  def set_order_status
    self.order_status_id = 1
  end

  def update_subtotal
    self[:subtotal] = subtotal
  end
end

user.rb

class User < ActiveRecord::Base
  has_many :identities, dependent: :destroy
  has_many :order
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :omniauthable, :invitable, :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable
end

order_item.rb:

class OrderItem < ActiveRecord::Base
  belongs_to :product
  belongs_to :order

  validates :quantity, presence: true, numericality: { only_integer: true, greater_than: 0 }
  validate :product_present
  validate :order_present

  before_save :finalize

  def unit_price
    if persisted?
      self[:unit_price]
    else
      product.price
    end
  end

  def total_price
    unit_price * quantity
  end

private
  def product_present
    if product.nil?
      errors.add(:product, "is not valid or is not active.")
    end
  end

  def order_present
    if order.nil?
      errors.add(:order, "is not a valid order.")
    end
  end

  def finalize
    self[:unit_price] = unit_price
    self[:total_price] = quantity * self[:unit_price]
  end
end

order_status.rb

class OrderStatus < ActiveRecord::Base
    has_many :orders
    belongs_to :user
end

每个订单商品的form_view.html.erb

 <%= form_for OrderItem.new, remote: true do |f| %>


        <div class="input-group">
          <%= f.hidden_field :quantity, value: 1, min: 1 %>
          <div class="input-group-btn">
            <%= f.hidden_field :product_id, value: product.id %>
            <%= f.submit "Add to Cart", data: { confirm: 'Are you sure that you want to order this item for current cycle?'}, class: "btn btn-default black-background white" %>
          </div>
        </div>
      <% end %>
    </div>

1 个答案:

答案 0 :(得分:0)

其中一种可能的解决方案是在您的订单中添加一个布尔标志,以表明它是“起始链”订单(一个开始30天计数器的订单)。将此标志设置为true的订单将开始30天计数器,而带有false标志的订单将是“常规”订单。

然后在创建时(在last_30_days_orders = Order .where("user_id = ? AND created_at > ?", current_user.id, DateTime.now - 30) if last_30_days_orders.any? {|order| order.starting_chain? } # there was a starting chain order in last 30 days if last_30_days_orders.length >= 3 # reject new order - already 3 orders in chain ... else # there is a chain and it has less then 3 orders yet - ready to go @order.starting_chain = false # proceed with saving ... end else # no orders within 30 days, or starting_chain order was more then 30 days ago # => new period starts @order.starting_chain = true # proceed with saving ... end 中)你做这样的事情:

import queue
import socket
import os

class PollableQueue(queue.Queue):
    def __init__(self):
        super().__init__()
        # Create a pair of connected sockets
        if os.name == 'posix':
            self._putsocket, self._getsocket = socket.socketpair()
        else:
            # Compatibility on non-POSIX systems
            server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            server.bind(('127.0.0.1', 0))
            server.listen(1)
            self._putsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self._putsocket.connect(server.getsockname())
            self._getsocket, _ = server.accept()
            server.close()

    def fileno(self):
        return self._getsocket.fileno()

    def put(self, item):
        super().put(item)
        self._putsocket.send(b'x')

    def get(self):
        self._getsocket.recv(1)
        return super().get()