电商网站订单系统设计
原文
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
endclass OrderStatus < ActiveRecord::Base
has_many :operations
def do operation
operations.find_by(name: operation).do_operation
end
endclass 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都存在数据库中,部署生产环境时需缓存
相关推荐
waixingxueren 2020-10-09
zhounan00 2020-07-28
jameszgw 2020-06-25
CharlesYooSky 2020-06-25
yourFriend 2020-06-25
THEEYE 2020-06-06
随心而作 2020-06-04
VanTYS 2020-06-03
Freeman00 2020-05-28
THEEYE 2020-05-27
quguang 2020-05-27
homesmile 2020-05-23
cgnine 2020-05-21
kangtingting0 2020-05-20
THEEYE 2020-05-05