comable 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +46 -0
- data/Rakefile +28 -0
- data/app/assets/javascripts/comable/application.js +13 -0
- data/app/assets/stylesheets/comable/application.css +13 -0
- data/app/controllers/comable/application_controller.rb +5 -0
- data/app/controllers/comable/carts_controller.rb +29 -0
- data/app/controllers/comable/orders_controller.rb +108 -0
- data/app/controllers/comable/products_controller.rb +11 -0
- data/app/helpers/comable/application_helper.rb +18 -0
- data/app/helpers/comable/products_helper.rb +55 -0
- data/app/models/comable/cart_item.rb +36 -0
- data/app/models/comable/customer.rb +115 -0
- data/app/models/comable/order.rb +29 -0
- data/app/models/comable/order_delivery.rb +12 -0
- data/app/models/comable/order_detail.rb +13 -0
- data/app/models/comable/product.rb +32 -0
- data/app/models/comable/stock.rb +31 -0
- data/app/views/comable/carts/show.slim +23 -0
- data/app/views/comable/orders/confirm.slim +25 -0
- data/app/views/comable/orders/create.slim +5 -0
- data/app/views/comable/orders/delivery.slim +8 -0
- data/app/views/comable/orders/new.slim +4 -0
- data/app/views/comable/orders/orderer.slim +7 -0
- data/app/views/comable/products/index.slim +11 -0
- data/app/views/comable/products/show.slim +20 -0
- data/app/views/layouts/comable/application.slim +11 -0
- data/config/locales/ja.yml +10 -0
- data/config/routes.rb +21 -0
- data/db/migrate/20131214194807_create_comable_products.rb +14 -0
- data/db/migrate/20140120024159_create_comable_cart_items.rb +12 -0
- data/db/migrate/20140120032559_create_comable_customers.rb +8 -0
- data/db/migrate/20140502060116_create_comable_stocks.rb +14 -0
- data/db/migrate/20140723175431_create_comable_orders.rb +13 -0
- data/db/migrate/20140723175624_create_comable_order_deliveries.rb +9 -0
- data/db/migrate/20140723175810_create_comable_order_details.rb +10 -0
- data/lib/comable.rb +8 -0
- data/lib/comable/cash_register.rb +90 -0
- data/lib/comable/decoratable.rb +10 -0
- data/lib/comable/engine.rb +8 -0
- data/lib/comable/migration.rb +16 -0
- data/lib/comable/version.rb +3 -0
- data/lib/tasks/comable_tasks.rake +4 -0
- metadata +284 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
module Comable
|
2
|
+
class Order < ActiveRecord::Base
|
3
|
+
include Decoratable
|
4
|
+
|
5
|
+
belongs_to :customer, class_name: Comable::Customer.name, foreign_key: Comable::Customer.table_name.singularize.foreign_key, autosave: false
|
6
|
+
has_many :order_deliveries, dependent: :destroy, class_name: Comable::OrderDelivery.name, foreign_key: table_name.singularize.foreign_key
|
7
|
+
|
8
|
+
accepts_nested_attributes_for :order_deliveries
|
9
|
+
|
10
|
+
validates :family_name, presence: true
|
11
|
+
validates :first_name, presence: true
|
12
|
+
|
13
|
+
before_create :generate_code
|
14
|
+
before_create :generate_ordered_at
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def generate_code
|
19
|
+
self.code = loop do
|
20
|
+
random_token = "C#{Array.new(11) { rand(9) }.join}"
|
21
|
+
break random_token unless self.class.exists?(code: random_token)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def generate_ordered_at
|
26
|
+
self.ordered_at = Time.now
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Comable
|
2
|
+
class OrderDelivery < ActiveRecord::Base
|
3
|
+
include Decoratable
|
4
|
+
|
5
|
+
belongs_to :order, class_name: Comable::Order.name, foreign_key: Comable::Order.table_name.singularize.foreign_key
|
6
|
+
has_many :order_details, dependent: :destroy, class_name: Comable::OrderDetail.name, foreign_key: table_name.singularize.foreign_key
|
7
|
+
|
8
|
+
accepts_nested_attributes_for :order_details
|
9
|
+
|
10
|
+
delegate :customer, to: :order
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Comable
|
2
|
+
class OrderDetail < ActiveRecord::Base
|
3
|
+
include Decoratable
|
4
|
+
|
5
|
+
belongs_to :stock, class_name: Comable::Stock.name, foreign_key: Comable::Stock.table_name.singularize.foreign_key
|
6
|
+
belongs_to :order_delivery, class_name: Comable::OrderDelivery.name, foreign_key: Comable::OrderDelivery.table_name.singularize.foreign_key
|
7
|
+
|
8
|
+
after_create :decrement_quantity!
|
9
|
+
delegate :decrement_quantity!, to: :stock
|
10
|
+
|
11
|
+
delegate :product, to: :stock
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Comable
|
2
|
+
class Product < ActiveRecord::Base
|
3
|
+
include Decoratable
|
4
|
+
|
5
|
+
has_many :stocks, class_name: Comable::Stock.name, foreign_key: table_name.singularize.foreign_key
|
6
|
+
after_create :create_stock
|
7
|
+
|
8
|
+
def unsold?
|
9
|
+
stocks.activated.unsold.exists?
|
10
|
+
end
|
11
|
+
|
12
|
+
def soldout?
|
13
|
+
!unsold?
|
14
|
+
end
|
15
|
+
|
16
|
+
def sku_h?
|
17
|
+
sku_h_item_name.present?
|
18
|
+
end
|
19
|
+
|
20
|
+
def sku_v?
|
21
|
+
sku_v_item_name.present?
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_method :sku?, :sku_h?
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def create_stock
|
29
|
+
stocks.create(code: code) unless stocks.exists?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Comable
|
2
|
+
class Stock < ActiveRecord::Base
|
3
|
+
include Decoratable
|
4
|
+
|
5
|
+
belongs_to :product, class_name: Comable::Product.name, foreign_key: Comable::Product.table_name.singularize.foreign_key
|
6
|
+
|
7
|
+
scope :activated, -> { where.not(product_id_num: nil) }
|
8
|
+
scope :unsold, -> { where('quantity > ?', 0) }
|
9
|
+
scope :soldout, -> { where('quantity <= ?', 0) }
|
10
|
+
|
11
|
+
delegate :price, to: :product
|
12
|
+
delegate :sku?, to: :product
|
13
|
+
|
14
|
+
def unsold?
|
15
|
+
return false if product_id_num.nil?
|
16
|
+
return false if quantity.nil?
|
17
|
+
quantity > 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def soldout?
|
21
|
+
!unsold?
|
22
|
+
end
|
23
|
+
|
24
|
+
def decrement_quantity!
|
25
|
+
with_lock do
|
26
|
+
# TODO: カラムマッピングのdecrementメソッドへの対応
|
27
|
+
update_attributes!(quantity: quantity.pred)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
h1 カート
|
2
|
+
|
3
|
+
ul.cart
|
4
|
+
- current_customer.cart.each do |cart_item|
|
5
|
+
- stock = cart_item.stock
|
6
|
+
- product = stock.product
|
7
|
+
li.product
|
8
|
+
h2.name
|
9
|
+
- if stock.sku?
|
10
|
+
- sku_name = stock.sku_h_choice_name
|
11
|
+
- sku_name += '/' + stock.sku_v_choice_name if stock.sku_v_choice_name.present?
|
12
|
+
= link_to product.name + "(#{sku_name})", comable.product_path(product)
|
13
|
+
- else
|
14
|
+
= link_to product.name, comable.product_path(product)
|
15
|
+
.caption
|
16
|
+
= product.caption
|
17
|
+
.price
|
18
|
+
= number_to_currency product.price
|
19
|
+
.quantity
|
20
|
+
= number_with_delimiter cart_item.quantity
|
21
|
+
|
22
|
+
.order
|
23
|
+
= link_to '注文', comable.new_order_path
|
@@ -0,0 +1,25 @@
|
|
1
|
+
h1 注文情報確認
|
2
|
+
|
3
|
+
.order
|
4
|
+
.orderer
|
5
|
+
.family_name
|
6
|
+
= @order.family_name
|
7
|
+
.first_name
|
8
|
+
= @order.first_name
|
9
|
+
.deliveries
|
10
|
+
- @order.order_deliveries.each do |order_delivery|
|
11
|
+
.first_name
|
12
|
+
= order_delivery.family_name
|
13
|
+
.first_name
|
14
|
+
= order_delivery.first_name
|
15
|
+
.details
|
16
|
+
- order_delivery.order_details.each do |order_detail|
|
17
|
+
.name
|
18
|
+
= order_detail.product.name
|
19
|
+
.quantity
|
20
|
+
= order_detail.price
|
21
|
+
.quantity
|
22
|
+
= order_detail.quantity
|
23
|
+
|
24
|
+
= form_for @order, as: :order, url: comable.order_path do |f|
|
25
|
+
= f.submit
|
@@ -0,0 +1,8 @@
|
|
1
|
+
h1 配送先情報入力
|
2
|
+
|
3
|
+
.orderer
|
4
|
+
= form_for @order, as: :order, url: comable.delivery_order_path do |f|
|
5
|
+
= f.fields_for :order_deliveries do |order_delivery|
|
6
|
+
= order_delivery.text_field :family_name, placeholder: '姓'
|
7
|
+
= order_delivery.text_field :first_name, placeholder: '名'
|
8
|
+
= f.submit
|
@@ -0,0 +1,20 @@
|
|
1
|
+
.product
|
2
|
+
h1.name
|
3
|
+
= @product.name
|
4
|
+
.caption
|
5
|
+
= @product.caption
|
6
|
+
.price
|
7
|
+
= number_to_currency @product.price
|
8
|
+
|
9
|
+
= form_tag comable.add_cart_path do
|
10
|
+
- if @product.sku?
|
11
|
+
.sku
|
12
|
+
= sku_table @product, border: 1
|
13
|
+
|
14
|
+
- if @product.unsold?
|
15
|
+
.add_cart
|
16
|
+
= hidden_field_tag :product_id, @product.id
|
17
|
+
= submit_tag 'カートに入れる'
|
18
|
+
- else
|
19
|
+
.sold_out
|
20
|
+
| 品切れ中
|
@@ -0,0 +1,11 @@
|
|
1
|
+
doctype html
|
2
|
+
html
|
3
|
+
head
|
4
|
+
title Comable
|
5
|
+
= stylesheet_link_tag "comable/application", media: "all"
|
6
|
+
= javascript_include_tag "comable/application"
|
7
|
+
= csrf_meta_tags
|
8
|
+
body
|
9
|
+
- flash.each do |name, msg|
|
10
|
+
= content_tag(:div, msg, id: "flash_#{name}")
|
11
|
+
== yield
|
data/config/routes.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Comable::Engine.routes.draw do
|
2
|
+
get '/' => 'products#index'
|
3
|
+
|
4
|
+
resources :products
|
5
|
+
|
6
|
+
resource :cart do
|
7
|
+
collection do
|
8
|
+
post :add
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
resource :order do
|
13
|
+
collection do
|
14
|
+
get :orderer
|
15
|
+
post :orderer
|
16
|
+
get :delivery
|
17
|
+
post :delivery
|
18
|
+
get :confirm
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateComableProducts < Comable::Migration
|
2
|
+
def change
|
3
|
+
create_table :comable_products do |t|
|
4
|
+
t.string :name, null: false
|
5
|
+
t.string :code, null: false
|
6
|
+
t.integer :price, null: false
|
7
|
+
t.text :caption
|
8
|
+
t.string :sku_h_item_name
|
9
|
+
t.string :sku_v_item_name
|
10
|
+
end
|
11
|
+
|
12
|
+
add_index :comable_products, :code, unique: true, name: :comable_products_idx_01
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreateComableCartItems < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :comable_cart_items do |t|
|
4
|
+
t.integer :comable_customer_id
|
5
|
+
t.integer :comable_stock_id, null: false
|
6
|
+
t.integer :quantity, default: 1, null: false
|
7
|
+
t.string :guest_token
|
8
|
+
end
|
9
|
+
|
10
|
+
add_index :comable_cart_items, [:comable_customer_id, :comable_stock_id], unique: true, name: :comable_cart_items_idx_01
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateComableStocks < Comable::Migration
|
2
|
+
def change
|
3
|
+
create_table :comable_stocks do |t|
|
4
|
+
t.integer :comable_product_id
|
5
|
+
t.integer :product_id_num
|
6
|
+
t.string :code, null: false
|
7
|
+
t.integer :quantity
|
8
|
+
t.string :sku_h_choice_name
|
9
|
+
t.string :sku_v_choice_name
|
10
|
+
end
|
11
|
+
|
12
|
+
add_index :comable_stocks, :code, unique: true, name: :comable_stocks_idx_01
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateComableOrders < Comable::Migration
|
2
|
+
def change
|
3
|
+
create_table :comable_orders do |t|
|
4
|
+
t.integer :comable_customer_id
|
5
|
+
t.string :code, null: false
|
6
|
+
t.string :family_name, null: false
|
7
|
+
t.string :first_name, null: false
|
8
|
+
t.datetime :ordered_at, null: false
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :comable_orders, :code, unique: true, name: :comable_orders_idx_01
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class CreateComableOrderDetails < Comable::Migration
|
2
|
+
def change
|
3
|
+
create_table :comable_order_details do |t|
|
4
|
+
t.integer :comable_order_delivery_id, null: false
|
5
|
+
t.integer :comable_stock_id, null: false
|
6
|
+
t.integer :price, null: false
|
7
|
+
t.integer :quantity, default: 1, null: false
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/comable.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
module Comable
|
2
|
+
class InvalidOrder < StandardError; end
|
3
|
+
|
4
|
+
class CashRegister
|
5
|
+
attr_accessor :customer
|
6
|
+
attr_accessor :order
|
7
|
+
|
8
|
+
def initialize(attributes)
|
9
|
+
@customer = attributes[:customer]
|
10
|
+
@order = @customer.orders.build(attributes[:order_attributes])
|
11
|
+
end
|
12
|
+
|
13
|
+
def build_order
|
14
|
+
assign_default_attributes_to_order
|
15
|
+
fail Comable::InvalidOrder if invalid
|
16
|
+
order
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_order
|
20
|
+
order = build_order
|
21
|
+
order.save
|
22
|
+
customer.reset_cart
|
23
|
+
order
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid
|
27
|
+
valid_cart && valid_stock
|
28
|
+
end
|
29
|
+
|
30
|
+
def invalid
|
31
|
+
!valid
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def valid_cart
|
37
|
+
cart = customer.cart
|
38
|
+
|
39
|
+
order.order_deliveries.map(&:order_details).flatten.each do |order_detail|
|
40
|
+
next unless order_detail.stock
|
41
|
+
result = cart.reject! { |cart_item| cart_item.stock == order_detail.stock }
|
42
|
+
return false if result.nil?
|
43
|
+
end
|
44
|
+
|
45
|
+
cart.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
def valid_stock
|
49
|
+
order.order_deliveries.map(&:order_details).flatten.each do |order_detail|
|
50
|
+
next unless order_detail.stock
|
51
|
+
return false unless order_detail.stock.unsold?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def assign_default_attributes_to_order
|
56
|
+
order.family_name ||= customer.family_name
|
57
|
+
order.first_name ||= customer.first_name
|
58
|
+
|
59
|
+
order.order_deliveries.build if order.order_deliveries.empty?
|
60
|
+
assign_default_attributes_to_order_deliveries
|
61
|
+
end
|
62
|
+
|
63
|
+
def assign_default_attributes_to_order_deliveries
|
64
|
+
order.order_deliveries.each do |order_delivery|
|
65
|
+
assign_default_attributes_to_order_delivery(order_delivery)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def assign_default_attributes_to_order_delivery(order_delivery)
|
70
|
+
order_delivery.family_name ||= customer.family_name
|
71
|
+
order_delivery.first_name ||= customer.first_name
|
72
|
+
|
73
|
+
assign_default_attributes_to_order_details(order_delivery) if first_order_detail?
|
74
|
+
end
|
75
|
+
|
76
|
+
def assign_default_attributes_to_order_details(order_delivery)
|
77
|
+
customer.cart.each do |cart_item|
|
78
|
+
order_delivery.order_details.build(
|
79
|
+
Comable::Stock.table_name.singularize.foreign_key => cart_item.stock.id,
|
80
|
+
:quantity => cart_item.quantity,
|
81
|
+
:price => cart_item.price
|
82
|
+
)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def first_order_detail?
|
87
|
+
order.order_deliveries.map(&:order_details).all?(&:empty?)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|