Commit 73f9c6f4 by ivan Lan

Add code about stock & Add validation uniq of buyer in Cart

parent 843c69a7
...@@ -30,6 +30,7 @@ module Shotengai ...@@ -30,6 +30,7 @@ module Shotengai
belongs_to :buyer, polymorphic: true, optional: true belongs_to :buyer, polymorphic: true, optional: true
default_scope { where(status: 'cart') } default_scope { where(status: 'cart') }
validates_uniqueness_of :buyer_id, scope: [:buyer_type]
# #
# class Order < Shotengai::Order # class Order < Shotengai::Order
......
...@@ -2,47 +2,48 @@ module Shotengai ...@@ -2,47 +2,48 @@ module Shotengai
module Controller module Controller
module Customer module Customer
class ProductSnapshotsController < Shotengai::Controller::Base class ProductSnapshotsController < Shotengai::Controller::Base
self.resources = ProductSnapshot # self.resources = ProductSnapshot
self.template_dir = 'shotengai/customer/snapshots/' # self.template_dir = 'shotengai/customer/snapshots/'
before_action :buyer_auth # before_action :buyer_auth
before_action :edit_only_unpaid, except: [:index, :show, :create] # before_action :edit_only_unpaid, except: [:index, :show, :create]
default_query do |resource, params| # default_query do |resource, params|
# /orders/:order_id/snapshots # # /orders/:order_id/snapshots
# /series/:series_id/snapshots # # /series/:series_id/snapshots
resource.where( # p 'come here'
params[:order_id] && { shotengai_order_id: params[:order_id] } # resource.where(
).where( # params[:order_id] && { shotengai_order_id: params[:order_id] }
params[:series_id] && { shotengai_series_id: params[:series_id] } # ).where(
) # params[:series_id] && { shotengai_series_id: params[:series_id] }
end # )
# end
index_query do |resource, params| # index_query do |resource, params|
params[:in_cart] ? resource.in_cart : resource.in_order # params[:in_cart] ? resource.in_cart : resource.in_order
end # end
# 不指定 order 时,默认创建在 cart 中 # # 不指定 order 时,默认创建在 cart 中
# TODO: WARNING: snapshots # # TODO: WARNING: snapshots
def create # def create
order_or_cart = Shotengai::Order.find_by_id(params[:order_id]) || @buyer.order_cart # order_or_cart = Shotengai::Order.find_by_id(params[:order_id]) || @buyer.order_cart
@resource = order_or_cart.product_snapshots.create!(resource_params) # @resource = order_or_cart.product_snapshots.create!(resource_params)
respond_with @resource, template: "#{@@template_dir}/show", status: 201 # respond_with @resource, template: "#{@@template_dir}/show", status: 201
end # end
private # private
def buyer_auth # def buyer_auth
@buyer = params[:buyer_type].constantize.find(params[:buyer_id]) # @buyer = params[:buyer_type].constantize.find(params[:buyer_id])
end # end
def resource_params # def resource_params
params.require(resource_key).permit( # params.require(resource_key).permit(
:count, :shotengai_series_id # :count, :shotengai_series_id
) # )
end # end
def edit_only_unpaid # def edit_only_unpaid
raise Shotengai::WebError.new('订单已支付,不可修改。', '-1', 403) unless @resource.order.unpaid? # raise Shotengai::WebError.new('订单已支付,不可修改。', '-1', 403) unless @resource.order.unpaid?
end # end
end end
end end
end end
......
...@@ -40,7 +40,7 @@ module Shotengai ...@@ -40,7 +40,7 @@ module Shotengai
state :unpaid, initial: true state :unpaid, initial: true
state :paid, :delivering, :received, :canceled, :evaluated state :paid, :delivering, :received, :canceled, :evaluated
event :pay, before: [:fill_snapshot, :set_pay_time] do event :pay, before: [:fill_snapshot, :cut_stock, :set_pay_time] do
transitions from: :unpaid, to: :paid transitions from: :unpaid, to: :paid
end end
...@@ -77,6 +77,12 @@ module Shotengai ...@@ -77,6 +77,12 @@ module Shotengai
} }
end end
def cut_stock
ActiveRecord::Base.transaction {
self.snapshots.each(&:cut_stock)
}
end
def set_pay_time def set_pay_time
self.update!(pay_time: Time.now) self.update!(pay_time: Time.now)
end end
......
...@@ -6,7 +6,7 @@ module Shotengai ...@@ -6,7 +6,7 @@ module Shotengai
# id :integer not null, primary key # id :integer not null, primary key
# original_price :decimal(9, 2) # original_price :decimal(9, 2)
# price :decimal(9, 2) # price :decimal(9, 2)
# stock :integer # stock :integer default(-1)
# spec :json # spec :json
# type :string(255) # type :string(255)
# meta :json # meta :json
...@@ -32,10 +32,13 @@ module Shotengai ...@@ -32,10 +32,13 @@ module Shotengai
# where(spec->'$.\"颜色\"' = ? and spec->'$.\"大小\"' = ? ,红色,S) # where(spec->'$.\"颜色\"' = ? and spec->'$.\"大小\"' = ? ,红色,S)
scope :query_spec_with_product, ->(val, product) { scope :query_spec_with_product, ->(val, product) {
return none unless val.keys.sort == product.spec.keys.sort if val.keys.sort == product.spec.keys.sort
keys = []; values = [] keys = []; values = []
val.map { |k, v| keys << "spec->'$.\"#{k}\"' = ? "; values << v } val.map { |k, v| keys << "spec->'$.\"#{k}\"' = ? "; values << v }
where(keys.join(' and '), *values) where(keys.join(' and '), *values)
else
self.none
end
} }
class << self class << self
...@@ -56,8 +59,7 @@ module Shotengai ...@@ -56,8 +59,7 @@ module Shotengai
end end
def cut_stock count def cut_stock count
self.stock -= count self.stock.eql?(-1) || self.update!(stock: self.stock - count)
self.save!
end end
private private
...@@ -71,7 +73,9 @@ module Shotengai ...@@ -71,7 +73,9 @@ module Shotengai
end end
def uniq_spec def uniq_spec
errors.add(:spec, 'Non uniq spec for the product.') if self.class.query_spec_with_product(self.spec, self.product).any? if self.class.query_spec_with_product(self.spec, self.product).where.not(id: self.id).any?
errors.add(:spec, 'Non uniq spec for the product.')
end
end end
def validate_stock def validate_stock
......
...@@ -72,6 +72,7 @@ module Shotengai ...@@ -72,6 +72,7 @@ module Shotengai
# 订单支付后 存储当时信息快照 # 订单支付后 存储当时信息快照
def copy_info def copy_info
# cut_stock
self.update!( self.update!(
original_price: series.original_price, original_price: series.original_price,
price: series.price, price: series.price,
...@@ -83,6 +84,10 @@ module Shotengai ...@@ -83,6 +84,10 @@ module Shotengai
) )
end end
def cut_stock
self.series.cut_stock
end
def meta def meta
read_attribute(:meta) || series.product.meta.merge(series.meta) read_attribute(:meta) || series.product.meta.merge(series.meta)
end end
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# id :integer not null, primary key # id :integer not null, primary key
# original_price :decimal(9, 2) # original_price :decimal(9, 2)
# price :decimal(9, 2) # price :decimal(9, 2)
# stock :integer # stock :integer default(-1)
# spec :json # spec :json
# type :string(255) # type :string(255)
# meta :json # meta :json
...@@ -18,7 +18,7 @@ FactoryGirl.define do ...@@ -18,7 +18,7 @@ FactoryGirl.define do
factory :test_series, class: 'TestGoodSeries' do factory :test_series, class: 'TestGoodSeries' do
original_price 100 original_price 100
price 80 price 80
stock 10 # stock 10
spec { spec {
{ {
"颜色" => "红色", "颜色" => "红色",
...@@ -41,7 +41,7 @@ FactoryGirl.define do ...@@ -41,7 +41,7 @@ FactoryGirl.define do
spec { spec {
{ {
"颜色" => "红色", "颜色" => "红色",
"大小" => "S", "大小" => "L",
} }
} }
# type # type
......
...@@ -67,20 +67,36 @@ RSpec.describe 'Shotengai Models' do ...@@ -67,20 +67,36 @@ RSpec.describe 'Shotengai Models' do
it 'validate' do it 'validate' do
expect(@series.spec.class).to eq(Hash) expect(@series.spec.class).to eq(Hash)
# 非法关键字 # 非法关键字
expect{ expect {
@series.update!(spec: {"颜色" => "红色", "大小" => 1111 }) @series.update!(spec: {"颜色" => "红色", "大小" => 1111 })
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
# 关键字缺失 # 关键字缺失
# require 'irb'
# binding.irb
expect{ expect{
@series.update!(spec: {"颜色" => "红色"}) @series.update!(spec: {"颜色" => "红色"})
}.to raise_error(ActiveRecord::RecordInvalid) }.to raise_error(ActiveRecord::RecordInvalid)
# uniq validate about spec # uniq validate about spec
expect {
TestGoodSeries.create!( TestGoodSeries.create!(
FactoryGirl.attribute_for(:test_series).merge( FactoryGirl.attributes_for(:test_series).merge(
{test_good: @good} {test_good: @good}
) )
) )
}.to raise_error(ActiveRecord::RecordInvalid)
end
it 'About Stock' do
# 默认为 -1 (无限库存)
@series.cut_stock(1000)
expect(@series.reload.stock).to eq(-1)
# 非无限库存
@series.update!(stock: 10)
@series.cut_stock(10)
expect(@series.reload.stock).to eq(0)
expect {
@series.cut_stock(20)
}.to raise_error(ActiveRecord::RecordInvalid)
end end
it 'Associations' do it 'Associations' do
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment