Commit cbf6bb70 by ivan Lan

Add JsonColumn & Improve spec & Add Shotengai::Model

parent ef84b6d6
......@@ -101,7 +101,7 @@ RSpec.describe "#{namespace}/product_snapshots", type: :request, capture_example
produces 'application/json'
consumes 'application/json'
response(200, description: 'successful') do
it { expect(JSON(response.body)['product_status_zh']).to eq('上架'), 'check product_status_zh' }
it { expect(JSON(response.body)['product_status_zh']).to eq('上架'), 'check product_status_zh' }
end
end
......
......@@ -2,8 +2,7 @@ require 'swagger_helper'
namespace = '<%= @namespace %>'
RSpec.describe "#{namespace}/products", type: :request, capture_examples: true, tags: ["#{namespace} API", "product"] do
before do
@merchant = Merchant.register "merchant", "password"
@auth_token = Merchant.login "merchant", "password"
@merchant = create(:merchant)
class Catalog < Shotengai::Catalog; end
@clothes = Catalog.create!(name: '衣服')
......@@ -17,8 +16,10 @@ RSpec.describe "#{namespace}/products", type: :request, capture_examples: true,
path "/#{namespace}/products" do
get(summary: '商家 商品列表') do
parameter 'Merchant-Token', in: :header, type: :string
let('Merchant-Token') { @auth_token.token }
parameter :manager_type, in: :query, type: :string
parameter :manager_id, in: :query, type: :integer
let(:manager_id) { @merchant.id }
let(:manager_type) { @merchant.class.name }
parameter :page, in: :query, type: :string
parameter :per_page, in: :query, type: :string
......@@ -41,15 +42,17 @@ RSpec.describe "#{namespace}/products", type: :request, capture_examples: true,
end
response(200, description: 'filter by status') do
before { @product_1.put_on_shelf! }
let(:status) { 'on_sale' }
before { @product_1.sold_out! }
let(:status) { 'not_on' }
it { expect(JSON.parse(response.body)['products'].count).to eq(1) }
end
end
post(summary: '管理员新建商品') do
parameter 'Merchant-Token', in: :header, type: :string
let('Merchant-Token') { @auth_token.token }
parameter :manager_type, in: :query, type: :string
parameter :manager_id, in: :query, type: :integer
let(:manager_id) { @merchant.id }
let(:manager_type) { @merchant.class.name }
parameter :product, in: :body, schema: {
type: :object, properties: {
......@@ -116,15 +119,17 @@ RSpec.describe "#{namespace}/products", type: :request, capture_examples: true,
parameter :ids, in: :query, type: :string
parameter :event, in: :query, type: :string
let(:ids) { @products.first(2).map(&:id) }
let(:event) { 'put_on_shelf' }
let(:event) { 'sold_out' }
parameter 'Merchant-Token', in: :header, type: :string
let('Merchant-Token') { @auth_token.token }
parameter :manager_type, in: :query, type: :string
parameter :manager_id, in: :query, type: :integer
let(:manager_id) { @merchant.id }
let(:manager_type) { @merchant.class.name }
produces 'application/json'
consumes 'application/json'
response(200, description: 'successful') do
it {
expect(Product.where(status: 'on_sale').map(&:id).sort).to eq(@products.first(2).map(&:id).sort)
expect(Product.where(manager: @merchant).not_on.map(&:id).sort).to eq(@products.first(2).map(&:id).sort)
}
end
end
......@@ -135,8 +140,10 @@ RSpec.describe "#{namespace}/products", type: :request, capture_examples: true,
let(:id) { @product_1.id }
get(summary: '商户 商品详情') do
parameter 'Merchant-Token', in: :header, type: :string
let('Merchant-Token') { @auth_token.token }
parameter :manager_type, in: :query, type: :string
parameter :manager_id, in: :query, type: :integer
let(:manager_id) { @merchant.id }
let(:manager_type) { @merchant.class.name }
produces 'application/json'
consumes 'application/json'
response(200, description: 'successful') do
......@@ -146,8 +153,10 @@ RSpec.describe "#{namespace}/products", type: :request, capture_examples: true,
end
end
patch(summary: 'update product') do
parameter 'Merchant-Token', in: :header, type: :string
let('Merchant-Token') { @auth_token.token }
parameter :manager_type, in: :query, type: :string
parameter :manager_id, in: :query, type: :integer
let(:manager_id) { @merchant.id }
let(:manager_type) { @merchant.class.name }
produces 'application/json'
consumes 'application/json'
......@@ -195,8 +204,10 @@ RSpec.describe "#{namespace}/products", type: :request, capture_examples: true,
end
delete(summary: 'delete product') do
parameter 'Merchant-Token', in: :header, type: :string
let('Merchant-Token') { @auth_token.token }
parameter :manager_type, in: :query, type: :string
parameter :manager_id, in: :query, type: :integer
let(:manager_id) { @merchant.id }
let(:manager_type) { @merchant.class.name }
produces 'application/json'
consumes 'application/json'
......@@ -210,13 +221,15 @@ RSpec.describe "#{namespace}/products", type: :request, capture_examples: true,
let(:id) { @product_1.id }
post(summary: '商户 上架商品') do
parameter 'Merchant-Token', in: :header, type: :string
let('Merchant-Token') { @auth_token.token }
parameter :manager_type, in: :query, type: :string
parameter :manager_id, in: :query, type: :integer
let(:manager_id) { @merchant.id }
let(:manager_type) { @merchant.class.name }
produces 'application/json'
consumes 'application/json'
response(200, description: 'successful') do
# it { p response.body }
before { @product_1.sold_out! }
end
end
end
......@@ -226,8 +239,10 @@ RSpec.describe "#{namespace}/products", type: :request, capture_examples: true,
let(:id) { @product_1.id }
post(summary: '商户 下架商品') do
parameter 'Merchant-Token', in: :header, type: :string
let('Merchant-Token') { @auth_token.token }
parameter :manager_type, in: :query, type: :string
parameter :manager_id, in: :query, type: :integer
let(:manager_id) { @merchant.id }
let(:manager_type) { @merchant.class.name }
before { @product_1.update!(status: 'on_sale') }
produces 'application/json'
......
module Shotengai
module JsonColumn
extend ActiveSupport::Concern
included do
end
class_methods do
def hash_columns *columns
columns.each do |column|
define_method("#{column}_input=") do |val|
val = val.map{ |h| { h[:key] => h[:val] } }.reduce(&:merge)
write_attribute(column, val)
end
define_method("#{column}_output") do
read_attribute(column).map {|key, val| { key: key, val: val } }
end
end
end
end
end
end
\ No newline at end of file
module Shotengai
class Model < ApplicationRecord
self.abstract_class = true
include Shotengai::JsonColumn
end
end
\ No newline at end of file
......@@ -29,7 +29,7 @@ module Shotengai
# index_shotengai_orders_on_type (type)
#
class Order < ActiveRecord::Base
class Order < Shotengai::Model
self.table_name = 'shotengai_orders'
belongs_to :buyer, polymorphic: true, optional: true#, touch: true
......@@ -38,6 +38,8 @@ module Shotengai
after_create :set_seq
hash_columns :spec, :meta
include AASM_DLC
aasm column: :status do
state :unpaid, initial: true
......
......@@ -26,10 +26,12 @@ module Shotengai
# index_shotengai_products_on_type (type)
#
class Shotengai::Product < ActiveRecord::Base
class Product < Shotengai::Model
require 'acts-as-taggable-on'
self.table_name = 'shotengai_products'
hash_columns :spec, :meta, :detail
belongs_to :manager, polymorphic: true, optional: true#, touch: true
validate :check_spec, if: :spec
......@@ -76,15 +78,6 @@ module Shotengai
super || {}
end
def spec_output
spec.map { |key, val|
{
key: key,
val: val,
}
}
end
class << self
def series_class
Shotengai::Series
......
......@@ -21,7 +21,7 @@ module Shotengai
# index_shotengai_series_on_type (type)
#
class Series < ActiveRecord::Base
class Series < Shotengai::Model
self.table_name = 'shotengai_series'
validates_presence_of :spec
validate :check_spec_value
......@@ -29,6 +29,8 @@ module Shotengai
validate :uniq_spec
validate :validate_stock
hash_columns :spec, :meta
delegate :title, :detail, :banners, :cover_image, :status, :status_zh, :manager, to: :product
scope :alive, -> { where.not(aasm_state: 'deleted') }
......
......@@ -30,15 +30,17 @@ module Shotengai
# index_shotengai_snapshots_on_type (type)
#
class Snapshot < ActiveRecord::Base
class Snapshot < Shotengai::Model
self.table_name = 'shotengai_snapshots'
validate :check_spec, if: :spec
validates :count, numericality: { only_integer: true, greater_than: 0 }
hash_columns :spec, :meta, :detail
validate :cannot_edit, if: :order_was_paid
before_destroy :cannot_edit, if: :order_was_paid
validate :cannot_edit_or_create, if: :already_disable?
validate :cannot_edit_or_create, if: :already_disable
belongs_to :shotengai_order, foreign_key: :shotengai_order_id,
class_name: 'Shotengai::Order', optional: true#, touch: true
......@@ -93,6 +95,10 @@ module Shotengai
super || series.manager
end
def product
series.product
end
# 订单支付后 存储当时信息快照
def copy_info
# cut_stock
......@@ -104,7 +110,7 @@ module Shotengai
banners: series.banners,
cover_image: series.cover_image,
detail: series.detail,
meta: (series.product.meta || {} ).merge(series.meta || {})
meta: (product.meta || {} ).merge(series.meta || {})
)
end
......@@ -153,7 +159,7 @@ module Shotengai
end
def cannot_edit_or_create
error.add(:id, '商品已下架,无法购买。')
errors.add(:id, '商品已下架,无法购买。')
end
def set_manager
......
......@@ -26,9 +26,9 @@
#
FactoryGirl.define do
factory :test_good, class: 'TestGood' do
factory :product, class: 'Product' do
title 'Test Product Title'
# status
status 'on_sale'
spec {
{
"颜色" => ["黑色", "红色", "白色"],
......@@ -39,36 +39,7 @@ FactoryGirl.define do
need_express true
# need_time_attr true
cover_image 'cover_image.image'
banners { [ 'image1', 'image2' ] }
detail {
{
"使用说明" => "xxxxxxxx...",
"产品参数" => "参数 参数..."
}
}
# type "
meta {
{
"meta1" => "111",
"meta2" => "222",
}
}
end
factory :other_good, class: 'OtherGood' do
title 'Test Product Title'
# status
spec {
{
"颜色" => ["黑色", "红色", "白色"],
"大小" => ["S", "M", "L"],
}
}
# default_series_id ''
need_express true
# need_time_attr true
cover_image 'cover_image.image'
banners { [ 'image1', 'image2' ] }
banners { [ 'image1', 'iamge2' ] }
detail {
{
"使用说明" => "xxxxxxxx...",
......
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