电商网站订单系统设计

原文 

http://oldfritter.iteye.com/blog/2103337

200行代码搞定订单系统主体

概述

订单更新绝大多数是控制订单状态的改变.在此,我将订单状态抽象成点(order_status),改变订单状态的方法称为operation,operation不直接与订单相关,只与order_status相关.

 
电商网站订单系统设计
 

当订单状态发生改变时,订单包含的操作便自然变更为新的可执行操作

样例

以下是一个电商网站的状态流转图

  
电商网站订单系统设计
 

我是这样做模型层的

class Order < ActiveRecord::Base
  belongs_to :order_status
  has_many :operations, through: :order_status


  def do operation, &block
   return 'No method match' unless operations.find_by(name: operation)
    block_given? ? send(operation, &block) : set_order_status(send(operation))
  end
    
  # 提醒买家,订单将要被自动确认收货,如果尚未到货,请点击延长收货时间
  # email或者短信
  def message_notice
    
  end
  
  private
  
  # 用户支付货款至my_site
  def pay_my_site &block
    set_order_status order_status.do __method__.to_s and save
    "#{yield}?target_uuid=#{uuid}&target_type=trade&amount=#{payment_amount}&paid_by=#{payment_way.name}&foo_type=Order" if block_given?#根据block返回一个支付页面
  end
  
  # 取消订单
  def cancel
    order_status.do __method__.to_s
  end
  
  # 系统自动取消订单
  def auto_cancel
    order_status.do __method__.to_s if operations.find_by(name: operation)
  end
  
  # 确认到款
  def payment_receive
    order_status.do __method__.to_s if spill?
  end
  
  # 取消并退款
  def cancel_with_refund
    refund_money
    order_status.do __method__.to_s
  end
  
  # 发货
  def shipping
    delay(run_at: 3.day.from_now).message_notice
    set_received_at and order_status.do __method__.to_s
  end
  
  # 退款
  def refund
    refund_money
    order_status.do __method__.to_s
  end
  
  # 确认收货
  def receive
    order_status.do __method__.to_s
  end
  
  # 延长收货时间
  def extend_time
    update_attribute :received_at, received_at + 7.days.from_now
    order_status.do __method__.to_s
  end
  
  # 到期自动确认收货(默认7天)
  def auto_receive
    order_status.do __method__.to_s
  end
  
  # 退货/换货
  def return_goods
    order_status.do __method__.to_s
  end
end
class OrderStatus < ActiveRecord::Base
  
  has_many :operations
  
  def do operation
    operations.find_by(name: operation).do_operation
  end
  
end
class Operation < ActiveRecord::Base
  
  belongs_to :order_status
  belongs_to :result, class_name: :OrderStatus
  
  def do_operation
    result
  end
  
end

简单的状态变迁列表

 
电商网站订单系统设计
 

我的初始化脚本(rake)

#encoding: utf-8
namespace :order_status do

  task init: :environment do
    Operation.delete_all
    File.open(File.expand_path('../../../docs/order_status', __FILE__)).each_line do |line|
      arr = line.split(/[\t\n]+/).first(7)
      order_status = OrderStatus.find_by name: arr[1]
      order_status = OrderStatus.create(name: arr[1]) if order_status.blank?
      result = OrderStatus.find_by name: arr[5]
      result = OrderStatus.create(name: arr[5]) if result.blank?

      Operation.create({
        name: arr[3],
        order_status: order_status,
        result: result,
        operator: arr[6]
      })
      
    end
  end
  
end

控制器是这样设计的

class CartsController < ApplicationController
  before_action :set_order, only: [:to_pay_page, :operate_by_buyer, :operate_by_seller, :buyer_operations,:seller_operations]

  # redirect_to pay_page
  # params: :id => order.id, :payment_name => 'alipay'
  # 需检测是否已经选择了支付方式
  def to_pay_page
    @order.payment_way = BasicSettings::PaymentWay.find_by name: params[:payment_name]
    pay_params = Proc.new {url = '/pays/pay'}
    redirect_to @order.do('pay_my_site', &pay_params)
  end

 # 买家操作
   # params: order.id, operation
   def operate_by_buyer
     if params[:operation] == 'pay_my_site'
       return redirect_to select_payment_carts_path(id: @order.id)
     end
     @order.do params[:operation] if @order.operations.find_by(operator: 'buyer', name: params[:operation])
     redirect_to controller: 'my/orders', action: 'index'
   end 

  # 卖家操作
  # params: order.id, operation
  def operate_by_seller
    @order.do params[:operation] if @order.operations.find_by(operator: 'seller', name: params[:operation])
    redirect_to controller: params[:controller], action: params[:action]
  end

  # 买家可执行的操作
  def buyer_operations
    render json: @order.operations.where(operator: 'buyer').collect{|t|t.name}.to_json
  end

  # 卖家可执行的操作
  def seller_operations
    render json: @order.operations.where(operator: 'seller').collect{|t|t.name}.to_json
  end

  private
  def set_order
    @order = Slms::Order.find_by id: params[:id]
  end

end

至此基本完工

注: 为了便于开发,order_status和operation都存在数据库中,部署生产环境时需缓存

相关推荐