comable_core 0.3.4 → 0.4.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 +4 -4
- data/app/helpers/comable/application_helper.rb +17 -10
- data/app/models/comable/ability.rb +1 -1
- data/app/models/comable/address.rb +2 -2
- data/app/models/comable/order/associations.rb +22 -0
- data/app/models/comable/order/callbacks.rb +43 -0
- data/app/models/comable/order/scopes.rb +17 -0
- data/app/models/comable/order/validations.rb +39 -0
- data/app/models/comable/order.rb +63 -72
- data/app/models/comable/order_item/csvable.rb +32 -0
- data/app/models/comable/{order_detail.rb → order_item.rb} +19 -10
- data/app/models/comable/payment.rb +82 -0
- data/app/models/comable/payment_method.rb +1 -0
- data/app/models/comable/product/csvable.rb +20 -0
- data/app/models/comable/product.rb +2 -7
- data/app/models/comable/shipment.rb +79 -0
- data/app/models/comable/stock/csvable.rb +26 -0
- data/app/models/comable/stock.rb +2 -17
- data/app/models/comable/tracker.rb +17 -0
- data/app/models/comable/{customer.rb → user.rb} +11 -23
- data/app/models/concerns/comable/checkout.rb +35 -36
- data/app/models/concerns/comable/importable.rb +67 -0
- data/app/views/comable/order_mailer/complete.text.erb +9 -8
- data/config/initializers/comma.rb +8 -0
- data/config/locales/en.yml +105 -14
- data/config/locales/ja.yml +92 -19
- data/db/migrate/{20140120032559_create_comable_customers.rb → 20140120032559_create_comable_users.rb} +6 -6
- data/db/migrate/20140723175431_create_comable_orders.rb +2 -4
- data/db/migrate/{20140723175810_create_comable_order_details.rb → 20140723175810_create_comable_order_items.rb} +3 -3
- data/db/migrate/20140817194104_create_comable_payment_methods.rb +1 -0
- data/db/migrate/20141024025526_create_comable_addresses.rb +1 -1
- data/db/migrate/20150423095210_create_comable_shipments.rb +12 -0
- data/db/migrate/20150511171940_create_comable_payments.rb +11 -0
- data/db/migrate/20150513185230_create_comable_trackers.rb +12 -0
- data/db/seeds/comable/{customers.rb → users.rb} +3 -3
- data/lib/comable/core/configuration.rb +7 -1
- data/lib/comable/core/engine.rb +0 -25
- data/lib/comable/payment_provider/base.rb +16 -0
- data/lib/comable_core.rb +6 -1
- data/lib/comma_extractor_extentions.rb +31 -0
- data/lib/generators/comable/install/templates/config/initializers/comable.rb +16 -1
- metadata +79 -8
- data/lib/comable/errors.rb +0 -4
@@ -0,0 +1,79 @@
|
|
1
|
+
module Comable
|
2
|
+
class Shipment < ActiveRecord::Base
|
3
|
+
include Comable::Ransackable
|
4
|
+
|
5
|
+
belongs_to :order, class_name: Comable::Order.name, inverse_of: :shipment
|
6
|
+
belongs_to :shipment_method, class_name: Comable::ShipmentMethod.name
|
7
|
+
|
8
|
+
before_validation :copy_attributes_from_shipment_method, unless: :order_completed?
|
9
|
+
|
10
|
+
validates :order, presence: true
|
11
|
+
validates :shipment_method, presence: true
|
12
|
+
validates :fee, presence: true, numericality: { greater_than_or_equal_to: 0 }
|
13
|
+
validates :tracking_number, length: { maximum: 255 }
|
14
|
+
|
15
|
+
delegate :name, to: :shipment_method
|
16
|
+
|
17
|
+
ransack_options ransackable_attributes: { except: [:order_id, :shipment_method_id] }
|
18
|
+
|
19
|
+
# The #state attribute assigns the following values:
|
20
|
+
#
|
21
|
+
# pending when Order is not able to ship (default)
|
22
|
+
# ready when Order is able to ship
|
23
|
+
# completed when Order is already shipped
|
24
|
+
# canceled when Order is canceled
|
25
|
+
# resumed when Order is resumed from the "canceled" state
|
26
|
+
state_machine initial: :pending do
|
27
|
+
state :pending
|
28
|
+
state :ready
|
29
|
+
state :completed
|
30
|
+
state :canceled
|
31
|
+
state :resumed
|
32
|
+
|
33
|
+
event :next_state do
|
34
|
+
transition :pending => :ready
|
35
|
+
transition :ready => :completed
|
36
|
+
end
|
37
|
+
|
38
|
+
event :ship do
|
39
|
+
transition :ready => :completed
|
40
|
+
end
|
41
|
+
|
42
|
+
event :cancel do
|
43
|
+
transition [:completed, :resumed] => :canceled
|
44
|
+
end
|
45
|
+
|
46
|
+
event :resume do
|
47
|
+
transition :canceled => :resumed
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class << self
|
52
|
+
def state_names
|
53
|
+
state_machine.states.keys
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def stated?(target_state)
|
58
|
+
target_state_index = self.class.state_names.index(target_state.to_sym)
|
59
|
+
current_state_index = self.class.state_names.index(state_name)
|
60
|
+
target_state_index < current_state_index
|
61
|
+
end
|
62
|
+
|
63
|
+
def completed?
|
64
|
+
state?(:completed) || state?(:resumed)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def order_completed?
|
70
|
+
order.completed?
|
71
|
+
end
|
72
|
+
|
73
|
+
def copy_attributes_from_shipment_method
|
74
|
+
self.attributes = {
|
75
|
+
fee: shipment_method.fee
|
76
|
+
}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Comable
|
2
|
+
class Stock < ActiveRecord::Base
|
3
|
+
module Csvable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
include Comable::Importable
|
7
|
+
|
8
|
+
included do
|
9
|
+
comma do
|
10
|
+
product_code
|
11
|
+
code
|
12
|
+
quantity
|
13
|
+
sku_h_choice_name
|
14
|
+
sku_v_choice_name
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
delegate :code, to: :product, prefix: true, allow_nil: true
|
19
|
+
|
20
|
+
def product_code=(code)
|
21
|
+
return if product_code == code
|
22
|
+
self.product = Comable::Product.find_by(code: code)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/app/models/comable/stock.rb
CHANGED
@@ -7,6 +7,7 @@ module Comable
|
|
7
7
|
include Comable::SkuItem
|
8
8
|
include Comable::SkuChoice
|
9
9
|
include Comable::Ransackable
|
10
|
+
include Comable::Stock::Csvable
|
10
11
|
|
11
12
|
belongs_to :product, class_name: Comable::Product.name
|
12
13
|
|
@@ -18,25 +19,15 @@ module Comable
|
|
18
19
|
# 品切れでない在庫インスタンスを返す
|
19
20
|
scope :stocked, -> { where('quantity > ?', 0) }
|
20
21
|
|
21
|
-
class << self
|
22
|
-
alias_method :unsold, :stocked
|
23
|
-
deprecate :unsold, deprecator: Comable::Deprecator.instance
|
24
|
-
end
|
25
|
-
|
26
22
|
# @!scope class
|
27
23
|
# 品切れの在庫インスタンスを返す
|
28
24
|
scope :unstocked, -> { where('quantity <= ?', 0) }
|
29
25
|
|
30
|
-
class << self
|
31
|
-
alias_method :soldout, :unstocked
|
32
|
-
deprecate :soldout, deprecator: Comable::Deprecator.instance
|
33
|
-
end
|
34
|
-
|
35
26
|
#
|
36
27
|
# @!endgroup
|
37
28
|
#
|
38
29
|
|
39
|
-
validates :product, presence:
|
30
|
+
validates :product, presence: { message: Comable.t('admin.is_not_exists') }
|
40
31
|
validates :code, presence: true, length: { maximum: 255 }
|
41
32
|
validates :sku_h_choice_name, length: { maximum: 255 }
|
42
33
|
validates :sku_v_choice_name, length: { maximum: 255 }
|
@@ -63,9 +54,6 @@ module Comable
|
|
63
54
|
(self.quantity - quantity) >= 0
|
64
55
|
end
|
65
56
|
|
66
|
-
alias_method :unsold?, :stocked?
|
67
|
-
deprecate :unsold?, deprecator: Comable::Deprecator.instance
|
68
|
-
|
69
57
|
# 在庫の有無を取得する
|
70
58
|
#
|
71
59
|
# @example
|
@@ -78,8 +66,5 @@ module Comable
|
|
78
66
|
def unstocked?(quantity: 1)
|
79
67
|
!stocked?(quantity: quantity)
|
80
68
|
end
|
81
|
-
|
82
|
-
alias_method :soldout?, :unstocked?
|
83
|
-
deprecate :soldout?, deprecator: Comable::Deprecator.instance
|
84
69
|
end
|
85
70
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Comable
|
2
|
+
class Tracker < ActiveRecord::Base
|
3
|
+
extend Enumerize
|
4
|
+
|
5
|
+
validates :name, presence: true, length: { maximum: 255 }
|
6
|
+
validates :tracker_id, length: { maximum: 255 }
|
7
|
+
validates :code, presence: true
|
8
|
+
validates :place, presence: true, length: { maximum: 255 }
|
9
|
+
|
10
|
+
scope :activated, -> { where(activate_flag: true) }
|
11
|
+
|
12
|
+
enumerize :place, in: %i(
|
13
|
+
everywhere
|
14
|
+
checkout
|
15
|
+
), scope: true
|
16
|
+
end
|
17
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Comable
|
2
|
-
class
|
2
|
+
class User < ActiveRecord::Base
|
3
3
|
include Comable::CartOwner
|
4
4
|
include Comable::RoleOwner
|
5
5
|
include Comable::Ransackable
|
@@ -15,7 +15,7 @@ module Comable
|
|
15
15
|
|
16
16
|
validates :email, presence: true, length: { maximum: 255 }
|
17
17
|
|
18
|
-
devise(*Comable::Config.devise_strategies[:
|
18
|
+
devise(*Comable::Config.devise_strategies[:user])
|
19
19
|
|
20
20
|
ransack_options ransackable_attributes: { except: [:encrypted_password, :reset_password_token, :reset_password_sent_at, :remember_created_at, :bill_address_id, :ship_address_id] }
|
21
21
|
|
@@ -62,28 +62,21 @@ module Comable
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def cart_items
|
65
|
-
|
65
|
+
incomplete_order.order_items
|
66
66
|
end
|
67
67
|
|
68
68
|
def incomplete_order
|
69
|
+
@incomplete_order = nil if @incomplete_order.try(:completed?)
|
69
70
|
@incomplete_order ||= find_incomplete_order || initialize_incomplete_order
|
70
71
|
end
|
71
72
|
|
72
|
-
def order(order_params = {})
|
73
|
-
Rails.logger.debug '[DEPRECATED] Comable::Customer#order is deprecated. Please use Comable::Order#next_state method.'
|
74
|
-
incomplete_order.attributes = order_params
|
75
|
-
incomplete_order.state = 'complete'
|
76
|
-
incomplete_order.complete!
|
77
|
-
incomplete_order.tap { reload }
|
78
|
-
end
|
79
|
-
|
80
73
|
def after_set_user
|
81
74
|
return unless current_guest_token
|
82
75
|
|
83
|
-
guest_order = Comable::Order.incomplete.preload(:
|
76
|
+
guest_order = Comable::Order.incomplete.preload(:order_items).where(guest_token: current_guest_token).first
|
84
77
|
return unless guest_order
|
85
78
|
|
86
|
-
|
79
|
+
incomplete_order.inherit!(guest_order)
|
87
80
|
inherit_cart_items(guest_order)
|
88
81
|
end
|
89
82
|
|
@@ -106,7 +99,7 @@ module Comable
|
|
106
99
|
|
107
100
|
def incomplete_order_attributes
|
108
101
|
{
|
109
|
-
|
102
|
+
user_id: id,
|
110
103
|
email: email
|
111
104
|
}
|
112
105
|
end
|
@@ -115,20 +108,15 @@ module Comable
|
|
115
108
|
guest_token ||= current_guest_token unless signed_in?
|
116
109
|
Comable::Order
|
117
110
|
.incomplete
|
118
|
-
.preload(:
|
111
|
+
.preload(:order_items)
|
119
112
|
.where(guest_token: guest_token)
|
120
|
-
.
|
113
|
+
.by_user(self)
|
121
114
|
.first
|
122
115
|
end
|
123
116
|
|
124
|
-
def inherit_order_state(guest_order)
|
125
|
-
return if incomplete_order.stated?(guest_order.state)
|
126
|
-
incomplete_order.next_state
|
127
|
-
end
|
128
|
-
|
129
117
|
def inherit_cart_items(guest_order)
|
130
|
-
guest_order.
|
131
|
-
move_cart_item(
|
118
|
+
guest_order.order_items.each do |order_item|
|
119
|
+
move_cart_item(order_item)
|
132
120
|
end
|
133
121
|
end
|
134
122
|
end
|
@@ -10,52 +10,35 @@ module Comable
|
|
10
10
|
state :shipment
|
11
11
|
state :payment
|
12
12
|
state :confirm
|
13
|
-
state :
|
13
|
+
state :completed
|
14
|
+
state :canceled
|
15
|
+
state :returned
|
16
|
+
state :resumed
|
14
17
|
|
15
18
|
event :next_state do
|
16
19
|
transition :cart => :orderer, if: :orderer_required?
|
17
20
|
transition [:cart, :orderer] => :delivery, if: :delivery_required?
|
18
21
|
transition [:cart, :orderer, :delivery] => :shipment, if: :shipment_required?
|
19
22
|
transition [:cart, :orderer, :delivery, :shipment] => :payment, if: :payment_required?
|
20
|
-
transition all - [:confirm, :
|
21
|
-
transition :confirm => :
|
23
|
+
transition all - [:confirm, :completed] => :confirm
|
24
|
+
transition :confirm => :completed
|
22
25
|
end
|
23
26
|
|
24
|
-
|
25
|
-
|
27
|
+
event :cancel do
|
28
|
+
transition to: :canceled, from: [:completed, :resumed], if: :allow_cancel?
|
26
29
|
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# TODO: Remove with_options
|
30
|
-
with_options if: -> { state?(:cart) } do |context|
|
31
|
-
context.validates :customer_id, presence: true, uniqueness: { scope: [:customer_id, :completed_at] }, unless: :guest_token
|
32
|
-
context.validates :guest_token, presence: true, uniqueness: { scope: [:guest_token, :completed_at] }, unless: :customer
|
33
|
-
end
|
34
|
-
|
35
|
-
with_options if: -> { stated?(:cart) } do |context|
|
36
|
-
context.validates :email, presence: true
|
37
|
-
end
|
38
30
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
with_options if: -> { stated?(:delivery) } do |context|
|
44
|
-
context.validates :ship_address, presence: true
|
45
|
-
end
|
46
|
-
|
47
|
-
with_options if: -> { stated?(:payment) && payment_required? } do |context|
|
48
|
-
context.validates :payment_method, presence: true
|
49
|
-
end
|
31
|
+
event :return do
|
32
|
+
transition to: :returned, from: [:completed, :resumed], if: :allow_return?
|
33
|
+
end
|
50
34
|
|
51
|
-
|
52
|
-
|
53
|
-
|
35
|
+
event :resume do
|
36
|
+
transition to: :resumed, from: :canceled
|
37
|
+
end
|
54
38
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
context.validates :total_price, presence: true
|
39
|
+
before_transition to: :completed, do: :complete!
|
40
|
+
after_transition to: :canceled, do: :restock!
|
41
|
+
after_transition to: :resumed, do: :unstock!
|
59
42
|
end
|
60
43
|
end
|
61
44
|
|
@@ -71,6 +54,10 @@ module Comable
|
|
71
54
|
target_state_index < current_state_index
|
72
55
|
end
|
73
56
|
|
57
|
+
def completed?
|
58
|
+
state?(:completed) || state?(:resumed)
|
59
|
+
end
|
60
|
+
|
74
61
|
def orderer_required?
|
75
62
|
bill_address.nil? || bill_address.new_record?
|
76
63
|
end
|
@@ -80,11 +67,23 @@ module Comable
|
|
80
67
|
end
|
81
68
|
|
82
69
|
def payment_required?
|
83
|
-
Comable::PaymentMethod.exists?
|
70
|
+
Comable::PaymentMethod.exists? && payment.nil?
|
84
71
|
end
|
85
72
|
|
86
73
|
def shipment_required?
|
87
|
-
Comable::ShipmentMethod.activated.exists?
|
74
|
+
Comable::ShipmentMethod.activated.exists? && shipment.nil?
|
75
|
+
end
|
76
|
+
|
77
|
+
def allow_cancel?
|
78
|
+
# TODO: Implement shipments
|
79
|
+
# !shipments.exists?
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
def allow_return?
|
84
|
+
# TODO: Implement shipments
|
85
|
+
# shipments.exists?
|
86
|
+
false
|
88
87
|
end
|
89
88
|
end
|
90
89
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Comable
|
2
|
+
module Importable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
class Exception < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
class UnknownFileType < Comable::Importable::Exception
|
9
|
+
end
|
10
|
+
|
11
|
+
class RecordInvalid < Comable::Importable::Exception
|
12
|
+
end
|
13
|
+
|
14
|
+
# from http://railscasts.com/episodes/396-importing-csv-and-excel
|
15
|
+
module ClassMethods
|
16
|
+
def import_from(file, primary_key: :code)
|
17
|
+
spreadsheet = open_spreadsheet(file)
|
18
|
+
read_spreadsheet(spreadsheet) do |header, row|
|
19
|
+
attributes = attributes_from_header_and_row(header, row)
|
20
|
+
record = find_by(primary_key => attributes[primary_key]) || new
|
21
|
+
begin
|
22
|
+
record.update_attributes!(attributes)
|
23
|
+
rescue ActiveRecord::RecordInvalid => e
|
24
|
+
raise RecordInvalid, "#{record.class.human_attribute_name(primary_key)} \"#{record.send(primary_key)}\": #{e.message}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def open_spreadsheet(file)
|
32
|
+
case File.extname(file.original_filename)
|
33
|
+
when '.csv' then Roo::CSV.new(file.path)
|
34
|
+
when '.xls' then Roo::Excel.new(file.path, nil, :ignore)
|
35
|
+
when '.xlsx' then Roo::Excelx.new(file.path, nil, :ignore)
|
36
|
+
else fail UnknownFileType, Comable.t('admin.unknown_file_type', filename: file.original_filename)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def read_spreadsheet(spreadsheet)
|
41
|
+
header = spreadsheet.row(1)
|
42
|
+
(2..spreadsheet.last_row).each do |i|
|
43
|
+
yield header, spreadsheet.row(i)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def attributes_from_header_and_row(header, row)
|
48
|
+
human_attributes = Hash[[header, row].transpose].to_hash
|
49
|
+
human_attributes_to_attributes(human_attributes)
|
50
|
+
end
|
51
|
+
|
52
|
+
def human_attributes_to_attributes(human_attributes)
|
53
|
+
comma_column_names.each.with_object({}) do |(key, _value), result|
|
54
|
+
human_key = Comma::HeaderExtractor.value_humanizer.call(key.to_sym, self)
|
55
|
+
result[key.to_sym] = human_attributes[human_key] if human_attributes[human_key]
|
56
|
+
result
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def comma_column_names(style = :default)
|
61
|
+
header_extractor_class = Comma::HeaderExtractor.dup
|
62
|
+
header_extractor_class.value_humanizer = -> (value, _model_class) { value.to_s }
|
63
|
+
extract_with(header_extractor_class, style)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -6,10 +6,10 @@
|
|
6
6
|
|
7
7
|
<%= Comable.t('order_mailer.complete.introductions', store_name: current_store.name) %>
|
8
8
|
|
9
|
-
<%-
|
10
|
-
<%- if
|
11
|
-
<%=
|
12
|
-
<%=
|
9
|
+
<%- shipment = @order.shipment %>
|
10
|
+
<%- if shipment %>
|
11
|
+
<%= @order.class.human_attribute_name(:shipment_method) %>:
|
12
|
+
<%= shipment.name %>
|
13
13
|
<%- end %>
|
14
14
|
|
15
15
|
<%= @order.class.human_attribute_name(:ship_address) %>:
|
@@ -22,19 +22,20 @@
|
|
22
22
|
<%= "#{@order.class.human_attribute_name(:code)}: #{@order.code}" %>
|
23
23
|
<%= "#{@order.class.human_attribute_name(:completed_at)}: #{I18n.l @order.completed_at.to_date}" %>
|
24
24
|
|
25
|
-
<%- @order.
|
26
|
-
<%= name_with_quantity
|
27
|
-
<%= number_to_currency
|
25
|
+
<%- @order.order_items.each do |order_item| %>
|
26
|
+
<%= name_with_quantity order_item.name_with_sku, order_item.quantity %>
|
27
|
+
<%= number_to_currency order_item.subtotal_price %>
|
28
28
|
|
29
29
|
<%- end %>
|
30
30
|
----------------------------------------------------------------------
|
31
31
|
|
32
32
|
<%= "#{@order.class.human_attribute_name(:item_total_price)}: #{number_to_currency @order.item_total_price}" %>
|
33
|
+
<%= "#{@order.class.human_attribute_name(:payment_fee)}: #{number_to_currency @order.payment_fee}" %>
|
33
34
|
<%= "#{@order.class.human_attribute_name(:shipment_fee)}: #{number_to_currency @order.shipment_fee}" %>
|
34
35
|
|
35
36
|
<%= "#{@order.class.human_attribute_name(:total_price)}: #{number_to_currency @order.total_price}" %>
|
36
37
|
|
37
|
-
<%= "#{@order.class.human_attribute_name(:payment_method)}: #{@order.
|
38
|
+
<%= "#{@order.class.human_attribute_name(:payment_method)}: #{@order.payment.name}\n" if @order.payment -%>
|
38
39
|
|
39
40
|
======================================================================
|
40
41
|
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# from https://github.com/comma-csv/comma/pull/50#issuecomment-22819269
|
2
|
+
Comma::HeaderExtractor.value_humanizer = lambda do |value, model_class|
|
3
|
+
if value.is_a?(String) || !model_class.respond_to?(:human_attribute_name)
|
4
|
+
Comma::HeaderExtractor::DEFAULT_VALUE_HUMANIZER.call(value, model_class)
|
5
|
+
else
|
6
|
+
model_class.human_attribute_name(value)
|
7
|
+
end
|
8
|
+
end
|