comable-core 0.6.0
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/Rakefile +97 -0
- data/app/assets/javascripts/comable/application.js +13 -0
- data/app/assets/stylesheets/comable/application.css +13 -0
- data/app/controllers/concerns/comable/permitted_attributes.rb +15 -0
- data/app/helpers/comable/application_helper.rb +84 -0
- data/app/helpers/comable/products_helper.rb +82 -0
- data/app/mailers/comable/order_mailer.rb +18 -0
- data/app/models/comable/ability.rb +18 -0
- data/app/models/comable/address.rb +39 -0
- data/app/models/comable/category.rb +72 -0
- data/app/models/comable/image.rb +15 -0
- data/app/models/comable/order.rb +121 -0
- data/app/models/comable/order/associations.rb +22 -0
- data/app/models/comable/order/callbacks.rb +43 -0
- data/app/models/comable/order/morrisable.rb +20 -0
- data/app/models/comable/order/scopes.rb +17 -0
- data/app/models/comable/order/validations.rb +39 -0
- data/app/models/comable/order_item.rb +98 -0
- data/app/models/comable/order_item/csvable.rb +32 -0
- data/app/models/comable/page.rb +30 -0
- data/app/models/comable/payment.rb +87 -0
- data/app/models/comable/payment_method.rb +27 -0
- data/app/models/comable/product.rb +55 -0
- data/app/models/comable/product/csvable.rb +20 -0
- data/app/models/comable/shipment.rb +85 -0
- data/app/models/comable/shipment_method.rb +9 -0
- data/app/models/comable/stock.rb +71 -0
- data/app/models/comable/stock/csvable.rb +26 -0
- data/app/models/comable/store.rb +30 -0
- data/app/models/comable/theme.rb +25 -0
- data/app/models/comable/tracker.rb +17 -0
- data/app/models/comable/user.rb +130 -0
- data/app/models/concerns/comable/cart_owner.rb +94 -0
- data/app/models/concerns/comable/checkout.rb +85 -0
- data/app/models/concerns/comable/importable.rb +67 -0
- data/app/models/concerns/comable/liquidable.rb +12 -0
- data/app/models/concerns/comable/product/search.rb +41 -0
- data/app/models/concerns/comable/ransackable.rb +38 -0
- data/app/models/concerns/comable/role_owner.rb +15 -0
- data/app/models/concerns/comable/sku_choice.rb +19 -0
- data/app/models/concerns/comable/sku_item.rb +17 -0
- data/app/uploaders/image_uploader.rb +7 -0
- data/app/views/comable/order_mailer/complete.text.erb +42 -0
- data/config/initializers/comma.rb +8 -0
- data/config/locales/en.yml +424 -0
- data/config/locales/ja.yml +425 -0
- data/db/migrate/20131214194807_create_comable_products.rb +15 -0
- data/db/migrate/20140120032559_create_comable_users.rb +46 -0
- data/db/migrate/20140502060116_create_comable_stocks.rb +14 -0
- data/db/migrate/20140723175431_create_comable_orders.rb +20 -0
- data/db/migrate/20140723175810_create_comable_order_items.rb +19 -0
- data/db/migrate/20140817194104_create_comable_payment_methods.rb +13 -0
- data/db/migrate/20140921191416_create_comable_shipment_methods.rb +11 -0
- data/db/migrate/20140926063541_create_comable_stores.rb +11 -0
- data/db/migrate/20141024025526_create_comable_addresses.rb +17 -0
- data/db/migrate/20150111031228_create_comable_categories.rb +10 -0
- data/db/migrate/20150111031229_create_comable_products_categories.rb +8 -0
- data/db/migrate/20150112173706_create_comable_images.rb +9 -0
- data/db/migrate/20150423095210_create_comable_shipments.rb +13 -0
- data/db/migrate/20150511171940_create_comable_payments.rb +12 -0
- data/db/migrate/20150513185230_create_comable_trackers.rb +12 -0
- data/db/migrate/20150519080729_create_comable_pages.rb +17 -0
- data/db/migrate/20150612143226_create_comable_themes.rb +15 -0
- data/db/migrate/20150612143445_add_theme_id_to_comable_stores.rb +7 -0
- data/db/seeds.rb +5 -0
- data/db/seeds/comable/users.rb +51 -0
- data/lib/comable/core.rb +48 -0
- data/lib/comable/core/configuration.rb +22 -0
- data/lib/comable/core/engine.rb +50 -0
- data/lib/comable/deprecator.rb +26 -0
- data/lib/comable/payment_provider.rb +14 -0
- data/lib/comable/payment_provider/base.rb +42 -0
- data/lib/comable/payment_provider/general.rb +15 -0
- data/lib/comable/state_machine_patch.rb +32 -0
- data/lib/comma_extractor_extentions.rb +31 -0
- data/lib/generators/comable/install/install_generator.rb +133 -0
- data/lib/generators/comable/install/templates/config/initializers/comable.rb +31 -0
- data/lib/tasks/comable_tasks.rake +4 -0
- metadata +346 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
module Comable
|
2
|
+
class Image < ActiveRecord::Base
|
3
|
+
include Comable::Liquidable
|
4
|
+
|
5
|
+
mount_uploader :file, ImageUploader
|
6
|
+
|
7
|
+
belongs_to :product, class_name: Comable::Product.name
|
8
|
+
|
9
|
+
liquid_methods :url
|
10
|
+
|
11
|
+
delegate :url, to: :file, allow_nil: true
|
12
|
+
delegate :current_path, to: :file, allow_nil: true
|
13
|
+
delegate :identifier, to: :file, allow_nil: true
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require_dependency 'comable/order/associations'
|
2
|
+
require_dependency 'comable/order/callbacks'
|
3
|
+
require_dependency 'comable/order/scopes'
|
4
|
+
require_dependency 'comable/order/validations'
|
5
|
+
require_dependency 'comable/order/morrisable'
|
6
|
+
|
7
|
+
module Comable
|
8
|
+
class Order < ActiveRecord::Base
|
9
|
+
include Comable::Checkout
|
10
|
+
include Comable::Ransackable
|
11
|
+
include Comable::Liquidable
|
12
|
+
include Comable::Order::Associations
|
13
|
+
include Comable::Order::Callbacks
|
14
|
+
include Comable::Order::Scopes
|
15
|
+
include Comable::Order::Validations
|
16
|
+
include Comable::Order::Morrisable
|
17
|
+
|
18
|
+
ransack_options attribute_select: { associations: [:payment, :shipment] }, ransackable_attributes: { except: [:bill_address_id, :ship_address_id] }
|
19
|
+
|
20
|
+
liquid_methods :code, :payment_fee, :shipment_fee, :item_total_price, :total_price, :order_items
|
21
|
+
|
22
|
+
delegate :full_name, to: :bill_address, allow_nil: true, prefix: :bill
|
23
|
+
delegate :full_name, to: :ship_address, allow_nil: true, prefix: :ship
|
24
|
+
delegate :state, :human_state_name, to: :payment, allow_nil: true, prefix: true
|
25
|
+
delegate :state, :human_state_name, to: :shipment, allow_nil: true, prefix: true
|
26
|
+
|
27
|
+
def complete!
|
28
|
+
ActiveRecord::Base.transaction do
|
29
|
+
run_callbacks :complete do
|
30
|
+
self.attributes = current_attributes
|
31
|
+
|
32
|
+
order_items.each(&:complete)
|
33
|
+
save!
|
34
|
+
|
35
|
+
payment.next_state! if payment
|
36
|
+
shipment.next_state! if shipment
|
37
|
+
|
38
|
+
touch(:completed_at)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :complete, :complete!
|
44
|
+
deprecate :complete, deprecator: Comable::Deprecator.instance
|
45
|
+
|
46
|
+
def restock!
|
47
|
+
order_items.each(&:restock)
|
48
|
+
save!
|
49
|
+
end
|
50
|
+
|
51
|
+
def unstock!
|
52
|
+
order_items.each(&:unstock)
|
53
|
+
save!
|
54
|
+
end
|
55
|
+
|
56
|
+
def stocked_items
|
57
|
+
order_items.to_a.select(&:unstocked?)
|
58
|
+
end
|
59
|
+
|
60
|
+
# 時価商品合計を取得
|
61
|
+
def current_item_total_price
|
62
|
+
order_items.to_a.sum(&:current_subtotal_price)
|
63
|
+
end
|
64
|
+
|
65
|
+
# 売価商品合計を取得
|
66
|
+
def item_total_price
|
67
|
+
order_items.to_a.sum(&:subtotal_price)
|
68
|
+
end
|
69
|
+
|
70
|
+
# 時価送料を取得
|
71
|
+
def current_shipment_fee
|
72
|
+
shipment.try(:fee) || 0
|
73
|
+
end
|
74
|
+
|
75
|
+
# Get the current payment fee
|
76
|
+
def current_payment_fee
|
77
|
+
payment.try(:fee) || 0
|
78
|
+
end
|
79
|
+
|
80
|
+
# 時価合計を取得
|
81
|
+
def current_total_price
|
82
|
+
current_item_total_price + current_payment_fee + current_shipment_fee
|
83
|
+
end
|
84
|
+
|
85
|
+
# Inherit from other Order
|
86
|
+
def inherit!(order)
|
87
|
+
self.bill_address ||= order.bill_address
|
88
|
+
self.ship_address ||= order.ship_address
|
89
|
+
self.payment ||= order.payment
|
90
|
+
self.shipment ||= order.shipment
|
91
|
+
|
92
|
+
stated?(order.state) ? save! : next_state!
|
93
|
+
end
|
94
|
+
|
95
|
+
def completed?
|
96
|
+
completed_at?
|
97
|
+
end
|
98
|
+
|
99
|
+
def paid?
|
100
|
+
payment ? payment.completed? : true
|
101
|
+
end
|
102
|
+
|
103
|
+
def shipped?
|
104
|
+
shipment ? shipment.completed? : true
|
105
|
+
end
|
106
|
+
|
107
|
+
def can_ship?
|
108
|
+
shipment && shipment.ready? && paid? && completed?
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def current_attributes
|
114
|
+
{
|
115
|
+
payment_fee: current_payment_fee,
|
116
|
+
shipment_fee: current_shipment_fee,
|
117
|
+
total_price: current_total_price
|
118
|
+
}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Comable
|
2
|
+
class Order < ActiveRecord::Base
|
3
|
+
module Associations
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
belongs_to :user, class_name: Comable::User.name, autosave: false
|
8
|
+
belongs_to :bill_address, class_name: Comable::Address.name, autosave: true, dependent: :destroy
|
9
|
+
belongs_to :ship_address, class_name: Comable::Address.name, autosave: true, dependent: :destroy
|
10
|
+
has_many :order_items, dependent: :destroy, class_name: Comable::OrderItem.name, inverse_of: :order
|
11
|
+
has_one :payment, dependent: :destroy, class_name: Comable::Payment.name, inverse_of: :order
|
12
|
+
has_one :shipment, dependent: :destroy, class_name: Comable::Shipment.name, inverse_of: :order
|
13
|
+
|
14
|
+
accepts_nested_attributes_for :bill_address
|
15
|
+
accepts_nested_attributes_for :ship_address
|
16
|
+
accepts_nested_attributes_for :order_items
|
17
|
+
accepts_nested_attributes_for :payment
|
18
|
+
accepts_nested_attributes_for :shipment
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Comable
|
2
|
+
class Order < ActiveRecord::Base
|
3
|
+
module Callbacks
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
define_model_callbacks :complete
|
8
|
+
|
9
|
+
before_validation :generate_guest_token, on: :create
|
10
|
+
before_validation :clone_addresses_from_user, on: :create
|
11
|
+
before_complete :generate_code
|
12
|
+
after_complete :clone_addresses_to_user
|
13
|
+
end
|
14
|
+
|
15
|
+
def generate_code
|
16
|
+
self.code = loop do
|
17
|
+
random_token = "C#{Array.new(11) { rand(9) }.join}"
|
18
|
+
break random_token unless self.class.exists?(code: random_token)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def generate_guest_token
|
23
|
+
return if user
|
24
|
+
self.guest_token ||= loop do
|
25
|
+
random_token = SecureRandom.urlsafe_base64(nil, false)
|
26
|
+
break random_token unless self.class.exists?(guest_token: random_token)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def clone_addresses_from_user
|
31
|
+
return unless user
|
32
|
+
self.bill_address ||= user.bill_address.try(:clone)
|
33
|
+
self.ship_address ||= user.ship_address.try(:clone)
|
34
|
+
end
|
35
|
+
|
36
|
+
def clone_addresses_to_user
|
37
|
+
return unless user
|
38
|
+
user.update_bill_address_by bill_address
|
39
|
+
user.update_ship_address_by ship_address
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Comable
|
2
|
+
class Order < ActiveRecord::Base
|
3
|
+
module Morrisable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def morris_keys
|
8
|
+
%w( count price )
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_morris
|
12
|
+
this = (Rails::VERSION::MAJOR == 3) ? scoped : all
|
13
|
+
this.group_by { |order| order.completed_at.to_date }.map do |date, orders|
|
14
|
+
{ date: date, count: orders.count, price: orders.sum(&:total_price) }
|
15
|
+
end.to_json
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Comable
|
2
|
+
class Order < ActiveRecord::Base
|
3
|
+
module Scopes
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
scope :complete, -> { where.not(completed_at: nil) }
|
8
|
+
scope :incomplete, -> { where(completed_at: nil) }
|
9
|
+
scope :by_user, -> (user) { where(user_id: user) }
|
10
|
+
scope :this_month, -> { where(completed_at: Time.now.beginning_of_month..Time.now.end_of_month) }
|
11
|
+
scope :this_week, -> { where(completed_at: Time.now.beginning_of_week..Time.now.end_of_week) }
|
12
|
+
scope :last_week, -> { where(completed_at: 1.week.ago.beginning_of_week..1.week.ago.end_of_week) }
|
13
|
+
scope :recent, -> { order('completed_at DESC, id DESC') }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Comable
|
2
|
+
class Order < ActiveRecord::Base
|
3
|
+
module Validations
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
validates :user_id, uniqueness: { scope: :completed_at }, if: :user
|
8
|
+
validates :guest_token, presence: true, uniqueness: { scope: :completed_at }, unless: :user
|
9
|
+
|
10
|
+
with_options if: -> { stated?(:cart) } do |context|
|
11
|
+
context.validates :email, presence: true, length: { maximum: 255 }
|
12
|
+
end
|
13
|
+
|
14
|
+
with_options if: -> { stated?(:orderer) } do |context|
|
15
|
+
context.validates :bill_address, presence: true
|
16
|
+
end
|
17
|
+
|
18
|
+
with_options if: -> { stated?(:delivery) } do |context|
|
19
|
+
context.validates :ship_address, presence: true
|
20
|
+
end
|
21
|
+
|
22
|
+
with_options if: -> { stated?(:shipment) && shipment_required? } do |context|
|
23
|
+
context.validates :shipment, presence: true
|
24
|
+
end
|
25
|
+
|
26
|
+
with_options if: -> { stated?(:payment) && payment_required? } do |context|
|
27
|
+
context.validates :payment, presence: true
|
28
|
+
end
|
29
|
+
|
30
|
+
with_options if: -> { stated?(:confirm) } do |context|
|
31
|
+
context.validates :code, presence: true
|
32
|
+
context.validates :payment_fee, presence: true
|
33
|
+
context.validates :shipment_fee, presence: true
|
34
|
+
context.validates :total_price, presence: true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Comable
|
2
|
+
class OrderItem < ActiveRecord::Base
|
3
|
+
include Comable::SkuItem
|
4
|
+
include Comable::SkuChoice
|
5
|
+
include Comable::Liquidable
|
6
|
+
include Comable::OrderItem::Csvable
|
7
|
+
|
8
|
+
belongs_to :stock, class_name: Comable::Stock.name, autosave: true
|
9
|
+
belongs_to :order, class_name: Comable::Order.name, inverse_of: :order_items
|
10
|
+
|
11
|
+
validates :quantity, numericality: { greater_than: 0 }
|
12
|
+
validate :valid_stock_quantity
|
13
|
+
|
14
|
+
liquid_methods :name, :name_with_sku, :code, :quantity, :price, :subtotal_price
|
15
|
+
|
16
|
+
delegate :product, to: :stock
|
17
|
+
delegate :image_url, to: :product
|
18
|
+
delegate :guest_token, to: :order
|
19
|
+
delegate :completed?, to: :order, allow_nil: true
|
20
|
+
|
21
|
+
before_validation :copy_attributes, unless: :completed?
|
22
|
+
|
23
|
+
def complete
|
24
|
+
unstock
|
25
|
+
end
|
26
|
+
|
27
|
+
def unstock
|
28
|
+
decrement_stock
|
29
|
+
end
|
30
|
+
|
31
|
+
def restock
|
32
|
+
increment_stock
|
33
|
+
end
|
34
|
+
|
35
|
+
# TODO: カート投入時との差額表示
|
36
|
+
def copy_attributes
|
37
|
+
self.attributes = current_attributes
|
38
|
+
end
|
39
|
+
|
40
|
+
# 時価を取得
|
41
|
+
def current_price
|
42
|
+
stock.price
|
43
|
+
end
|
44
|
+
|
45
|
+
# 時価小計を取得
|
46
|
+
def current_subtotal_price
|
47
|
+
current_price * quantity
|
48
|
+
end
|
49
|
+
|
50
|
+
# 売価小計を取得
|
51
|
+
def subtotal_price
|
52
|
+
price * quantity
|
53
|
+
end
|
54
|
+
|
55
|
+
def unstocked?
|
56
|
+
stock_with_clean_quantity do |stock|
|
57
|
+
stock.unstocked?(quantity: quantity)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def valid_stock_quantity
|
64
|
+
return unless unstocked?
|
65
|
+
errors.add :quantity, Comable.t('errors.messages.out_of_stock', name: stock.name_with_sku)
|
66
|
+
end
|
67
|
+
|
68
|
+
def stock_with_clean_quantity
|
69
|
+
quantity_will = stock.quantity
|
70
|
+
stock.quantity = stock.quantity_was if stock.quantity_was
|
71
|
+
yield stock
|
72
|
+
ensure
|
73
|
+
stock.quantity = quantity_will
|
74
|
+
end
|
75
|
+
|
76
|
+
def decrement_stock
|
77
|
+
stock.lock!
|
78
|
+
stock.quantity -= quantity
|
79
|
+
end
|
80
|
+
|
81
|
+
def increment_stock
|
82
|
+
stock.lock!
|
83
|
+
stock.quantity += quantity
|
84
|
+
end
|
85
|
+
|
86
|
+
def current_attributes
|
87
|
+
{
|
88
|
+
name: product.name,
|
89
|
+
code: stock.code,
|
90
|
+
price: stock.price,
|
91
|
+
sku_h_item_name: product.sku_h_item_name,
|
92
|
+
sku_v_item_name: product.sku_v_item_name,
|
93
|
+
sku_h_choice_name: stock.sku_h_choice_name,
|
94
|
+
sku_v_choice_name: stock.sku_v_choice_name
|
95
|
+
}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Comable
|
2
|
+
class OrderItem < ActiveRecord::Base
|
3
|
+
module Csvable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
comma do
|
8
|
+
__association__ order: :code
|
9
|
+
__association__ order: :email
|
10
|
+
__association__ order: :payment_fee
|
11
|
+
__association__ order: :shipment_fee
|
12
|
+
__association__ order: :total_price
|
13
|
+
__association__ order: { bill_address: :family_name }
|
14
|
+
__association__ order: { bill_address: :first_name }
|
15
|
+
__association__ order: { bill_address: :zip_code }
|
16
|
+
__association__ order: { bill_address: :state_name }
|
17
|
+
__association__ order: { bill_address: :city }
|
18
|
+
__association__ order: { bill_address: :detail }
|
19
|
+
__association__ order: { bill_address: :phone_number }
|
20
|
+
name
|
21
|
+
code
|
22
|
+
price
|
23
|
+
sku_h_item_name
|
24
|
+
sku_v_item_name
|
25
|
+
sku_h_choice_name
|
26
|
+
sku_v_choice_name
|
27
|
+
quantity
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Comable
|
2
|
+
class Page < ActiveRecord::Base
|
3
|
+
include Comable::Ransackable
|
4
|
+
|
5
|
+
extend FriendlyId
|
6
|
+
friendly_id :title, use: :slugged
|
7
|
+
|
8
|
+
validates :title, length: { maximum: 255 }, presence: true
|
9
|
+
validates :content, presence: true
|
10
|
+
validates :page_title, length: { maximum: 255 }
|
11
|
+
validates :meta_description, length: { maximum: 255 }
|
12
|
+
validates :meta_keywords, length: { maximum: 255 }
|
13
|
+
validates :slug, length: { maximum: 255 }, presence: true, uniqueness: true
|
14
|
+
|
15
|
+
PREVIEW_SESSION_KEY = :preview_page
|
16
|
+
|
17
|
+
def published?
|
18
|
+
published_at.present? && published_at <= Time.now
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_slug
|
22
|
+
id ||= self.class.maximum(:id).next
|
23
|
+
"pages_#{id}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def normalize_slug(string)
|
27
|
+
normalize_friendly_id(string).presence || default_slug
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|