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.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +97 -0
  4. data/app/assets/javascripts/comable/application.js +13 -0
  5. data/app/assets/stylesheets/comable/application.css +13 -0
  6. data/app/controllers/concerns/comable/permitted_attributes.rb +15 -0
  7. data/app/helpers/comable/application_helper.rb +84 -0
  8. data/app/helpers/comable/products_helper.rb +82 -0
  9. data/app/mailers/comable/order_mailer.rb +18 -0
  10. data/app/models/comable/ability.rb +18 -0
  11. data/app/models/comable/address.rb +39 -0
  12. data/app/models/comable/category.rb +72 -0
  13. data/app/models/comable/image.rb +15 -0
  14. data/app/models/comable/order.rb +121 -0
  15. data/app/models/comable/order/associations.rb +22 -0
  16. data/app/models/comable/order/callbacks.rb +43 -0
  17. data/app/models/comable/order/morrisable.rb +20 -0
  18. data/app/models/comable/order/scopes.rb +17 -0
  19. data/app/models/comable/order/validations.rb +39 -0
  20. data/app/models/comable/order_item.rb +98 -0
  21. data/app/models/comable/order_item/csvable.rb +32 -0
  22. data/app/models/comable/page.rb +30 -0
  23. data/app/models/comable/payment.rb +87 -0
  24. data/app/models/comable/payment_method.rb +27 -0
  25. data/app/models/comable/product.rb +55 -0
  26. data/app/models/comable/product/csvable.rb +20 -0
  27. data/app/models/comable/shipment.rb +85 -0
  28. data/app/models/comable/shipment_method.rb +9 -0
  29. data/app/models/comable/stock.rb +71 -0
  30. data/app/models/comable/stock/csvable.rb +26 -0
  31. data/app/models/comable/store.rb +30 -0
  32. data/app/models/comable/theme.rb +25 -0
  33. data/app/models/comable/tracker.rb +17 -0
  34. data/app/models/comable/user.rb +130 -0
  35. data/app/models/concerns/comable/cart_owner.rb +94 -0
  36. data/app/models/concerns/comable/checkout.rb +85 -0
  37. data/app/models/concerns/comable/importable.rb +67 -0
  38. data/app/models/concerns/comable/liquidable.rb +12 -0
  39. data/app/models/concerns/comable/product/search.rb +41 -0
  40. data/app/models/concerns/comable/ransackable.rb +38 -0
  41. data/app/models/concerns/comable/role_owner.rb +15 -0
  42. data/app/models/concerns/comable/sku_choice.rb +19 -0
  43. data/app/models/concerns/comable/sku_item.rb +17 -0
  44. data/app/uploaders/image_uploader.rb +7 -0
  45. data/app/views/comable/order_mailer/complete.text.erb +42 -0
  46. data/config/initializers/comma.rb +8 -0
  47. data/config/locales/en.yml +424 -0
  48. data/config/locales/ja.yml +425 -0
  49. data/db/migrate/20131214194807_create_comable_products.rb +15 -0
  50. data/db/migrate/20140120032559_create_comable_users.rb +46 -0
  51. data/db/migrate/20140502060116_create_comable_stocks.rb +14 -0
  52. data/db/migrate/20140723175431_create_comable_orders.rb +20 -0
  53. data/db/migrate/20140723175810_create_comable_order_items.rb +19 -0
  54. data/db/migrate/20140817194104_create_comable_payment_methods.rb +13 -0
  55. data/db/migrate/20140921191416_create_comable_shipment_methods.rb +11 -0
  56. data/db/migrate/20140926063541_create_comable_stores.rb +11 -0
  57. data/db/migrate/20141024025526_create_comable_addresses.rb +17 -0
  58. data/db/migrate/20150111031228_create_comable_categories.rb +10 -0
  59. data/db/migrate/20150111031229_create_comable_products_categories.rb +8 -0
  60. data/db/migrate/20150112173706_create_comable_images.rb +9 -0
  61. data/db/migrate/20150423095210_create_comable_shipments.rb +13 -0
  62. data/db/migrate/20150511171940_create_comable_payments.rb +12 -0
  63. data/db/migrate/20150513185230_create_comable_trackers.rb +12 -0
  64. data/db/migrate/20150519080729_create_comable_pages.rb +17 -0
  65. data/db/migrate/20150612143226_create_comable_themes.rb +15 -0
  66. data/db/migrate/20150612143445_add_theme_id_to_comable_stores.rb +7 -0
  67. data/db/seeds.rb +5 -0
  68. data/db/seeds/comable/users.rb +51 -0
  69. data/lib/comable/core.rb +48 -0
  70. data/lib/comable/core/configuration.rb +22 -0
  71. data/lib/comable/core/engine.rb +50 -0
  72. data/lib/comable/deprecator.rb +26 -0
  73. data/lib/comable/payment_provider.rb +14 -0
  74. data/lib/comable/payment_provider/base.rb +42 -0
  75. data/lib/comable/payment_provider/general.rb +15 -0
  76. data/lib/comable/state_machine_patch.rb +32 -0
  77. data/lib/comma_extractor_extentions.rb +31 -0
  78. data/lib/generators/comable/install/install_generator.rb +133 -0
  79. data/lib/generators/comable/install/templates/config/initializers/comable.rb +31 -0
  80. data/lib/tasks/comable_tasks.rake +4 -0
  81. metadata +346 -0
@@ -0,0 +1,87 @@
1
+ module Comable
2
+ class Payment < ActiveRecord::Base
3
+ include Comable::Ransackable
4
+
5
+ belongs_to :order, class_name: Comable::Order.name, inverse_of: :payment
6
+ belongs_to :payment_method, class_name: Comable::PaymentMethod.name
7
+
8
+ before_validation :copy_attributes_from_payment_method, unless: :order_completed?
9
+
10
+ validates :order, presence: true
11
+ validates :payment_method, presence: true
12
+ validates :fee, presence: true, numericality: { greater_than_or_equal_to: 0 }
13
+
14
+ delegate :name, to: :payment_method
15
+ delegate :payment_provider, to: :payment_method
16
+ delegate :authorize!, :complete!, :cancel!, :resume!, to: :payment_provider, prefix: :provider
17
+
18
+ ransack_options ransackable_attributes: { except: [:order_id, :payment_method_id] }
19
+
20
+ # The #state attribute assigns the following values:
21
+ #
22
+ # pending when Order is not able to pay (default)
23
+ # ready when Order is able to pay
24
+ # completed when Order is already paid
25
+ # canceled when Order is canceled
26
+ # resumed when Order is resumed from the "canceled" state
27
+ state_machine initial: :pending do
28
+ state :pending
29
+ state :ready
30
+ state :completed
31
+ state :canceled
32
+ state :resumed
33
+
34
+ event :next_state do
35
+ transition :pending => :ready
36
+ transition :ready => :completed
37
+ end
38
+
39
+ event :cancel do
40
+ transition [:completed, :resumed] => :canceled
41
+ end
42
+
43
+ event :resume do
44
+ transition :canceled => :resumed
45
+ end
46
+
47
+ after_transition to: :ready, do: :next_state!
48
+ before_transition to: :ready, do: -> (s) { s.provider_authorize! }
49
+ before_transition to: :completed, do: -> (s) { s.complete! }
50
+ before_transition to: :canceled, do: -> (s) { s.provider_cancel! }
51
+ before_transition to: :canceled, do: -> (s) { s.provider_resume! }
52
+ end
53
+
54
+ class << self
55
+ def state_names
56
+ state_machine.states.keys
57
+ end
58
+ end
59
+
60
+ def stated?(target_state)
61
+ target_state_index = self.class.state_names.index(target_state.to_sym)
62
+ current_state_index = self.class.state_names.index(state_name)
63
+ target_state_index < current_state_index
64
+ end
65
+
66
+ def completed?
67
+ completed_at?
68
+ end
69
+
70
+ def complete!
71
+ provider_complete!
72
+ touch :completed_at
73
+ end
74
+
75
+ private
76
+
77
+ def order_completed?
78
+ order.completed?
79
+ end
80
+
81
+ def copy_attributes_from_payment_method
82
+ self.attributes = {
83
+ fee: payment_method.fee
84
+ }
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,27 @@
1
+ module Comable
2
+ class PaymentMethod < ActiveRecord::Base
3
+ validates :name, presence: true, length: { maximum: 255 }
4
+ validates :payment_provider_type, presence: true, length: { maximum: 255 }
5
+ validates :payment_provider_kind, presence: true, numericality: { greater_than_or_equal_to: 0 }
6
+ validates :fee, presence: true, numericality: { greater_than_or_equal_to: 0 }
7
+ validates :enable_price_from, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
8
+ validates :enable_price_to, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
9
+
10
+ def payment_provider
11
+ return unless Object.const_defined?(payment_provider_type)
12
+ Object.const_get(payment_provider_type)
13
+ end
14
+
15
+ def payment_provider_name
16
+ payment_provider.display_name
17
+ end
18
+
19
+ def payment_provider_kind_key
20
+ payment_provider.kind.keys.slice(payment_provider_kind)
21
+ end
22
+
23
+ def payment_provider_kind_name
24
+ payment_provider.kind.slice(payment_provider_kind_key).values.first
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,55 @@
1
+ module Comable
2
+ class Product < ActiveRecord::Base
3
+ include Comable::SkuItem
4
+ include Comable::Ransackable
5
+ include Comable::Liquidable
6
+ include Comable::Product::Search
7
+ include Comable::Product::Csvable
8
+
9
+ has_many :stocks, class_name: Comable::Stock.name, dependent: :destroy
10
+ has_many :images, class_name: Comable::Image.name, dependent: :destroy
11
+ has_and_belongs_to_many :categories, class_name: Comable::Category.name, join_table: :comable_products_categories
12
+
13
+ accepts_nested_attributes_for :images, allow_destroy: true
14
+
15
+ validates :name, presence: true, length: { maximum: 255 }
16
+ validates :code, presence: true, length: { maximum: 255 }
17
+ validates :price, presence: true, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
18
+ validates :sku_h_item_name, length: { maximum: 255 }
19
+ validates :sku_v_item_name, length: { maximum: 255 }
20
+
21
+ liquid_methods :id, :code, :name, :price, :images, :image_url
22
+
23
+ ransack_options attribute_select: { associations: :stocks }
24
+
25
+ # Add conditions for the images association.
26
+ # Override method of the images association to support Rails 3.x.
27
+ def images
28
+ super.order(:id)
29
+ end
30
+
31
+ def image_url
32
+ image = images.first
33
+ return image.url if image
34
+ 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTcxIiBoZWlnaHQ9IjE4MCIgdmlld0JveD0iMCAwIDE3MSAxODAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxkZWZzLz48cmVjdCB3aWR0aD0iMTcxIiBoZWlnaHQ9IjE4MCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjU4IiB5PSI5MCIgc3R5bGU9ImZpbGw6I0FBQUFBQTtmb250LXdlaWdodDpib2xkO2ZvbnQtZmFtaWx5OkFyaWFsLCBIZWx2ZXRpY2EsIE9wZW4gU2Fucywgc2Fucy1zZXJpZiwgbW9ub3NwYWNlO2ZvbnQtc2l6ZToxMHB0O2RvbWluYW50LWJhc2VsaW5lOmNlbnRyYWwiPjE3MXgxODA8L3RleHQ+PC9nPjwvc3ZnPg=='
35
+ end
36
+
37
+ def stocked?
38
+ stocks.stocked.exists?
39
+ end
40
+
41
+ def unstocked?
42
+ !stocked?
43
+ end
44
+
45
+ def category_path_names=(category_path_names, delimiter: Comable::Category::DEFAULT_PATH_NAME_DELIMITER)
46
+ self.categories = Comable::Category.find_by_path_names(category_path_names, delimiter: delimiter)
47
+ end
48
+
49
+ private
50
+
51
+ def create_stock
52
+ stocks.create(code: code) unless stocks.exists?
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,20 @@
1
+ module Comable
2
+ class Product < ActiveRecord::Base
3
+ module Csvable
4
+ extend ActiveSupport::Concern
5
+
6
+ include Comable::Importable
7
+
8
+ included do
9
+ comma do
10
+ name
11
+ code
12
+ price
13
+ caption
14
+ sku_h_item_name
15
+ sku_v_item_name
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,85 @@
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
+
50
+ before_transition to: :completed, do: -> (s) { s.complete! }
51
+ end
52
+
53
+ class << self
54
+ def state_names
55
+ state_machine.states.keys
56
+ end
57
+ end
58
+
59
+ def stated?(target_state)
60
+ target_state_index = self.class.state_names.index(target_state.to_sym)
61
+ current_state_index = self.class.state_names.index(state_name)
62
+ target_state_index < current_state_index
63
+ end
64
+
65
+ def completed?
66
+ completed_at?
67
+ end
68
+
69
+ def complete!
70
+ touch :completed_at
71
+ end
72
+
73
+ private
74
+
75
+ def order_completed?
76
+ order.completed?
77
+ end
78
+
79
+ def copy_attributes_from_shipment_method
80
+ self.attributes = {
81
+ fee: shipment_method.fee
82
+ }
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,9 @@
1
+ module Comable
2
+ class ShipmentMethod < ActiveRecord::Base
3
+ validates :name, presence: true, length: { maximum: 255 }
4
+ validates :fee, presence: true, numericality: { greater_than_or_equal_to: 0 }
5
+ validates :traking_url, length: { maximum: 255 }
6
+
7
+ scope :activated, -> { where(activated_flag: true) }
8
+ end
9
+ end
@@ -0,0 +1,71 @@
1
+ module Comable
2
+ #
3
+ # 在庫モデル。
4
+ # 商品に複数紐付き、品数やSKU(Stock Keeping Unit)情報を保持する。
5
+ #
6
+ class Stock < ActiveRecord::Base
7
+ include Comable::SkuItem
8
+ include Comable::SkuChoice
9
+ include Comable::Ransackable
10
+ include Comable::Liquidable
11
+ include Comable::Stock::Csvable
12
+
13
+ belongs_to :product, class_name: Comable::Product.name
14
+
15
+ #
16
+ # @!group Scope
17
+ #
18
+
19
+ # @!scope class
20
+ # 品切れでない在庫インスタンスを返す
21
+ scope :stocked, -> { where('quantity > ?', 0) }
22
+
23
+ # @!scope class
24
+ # 品切れの在庫インスタンスを返す
25
+ scope :unstocked, -> { where('quantity <= ?', 0) }
26
+
27
+ #
28
+ # @!endgroup
29
+ #
30
+
31
+ validates :product, presence: { message: Comable.t('admin.is_not_exists') }
32
+ validates :code, presence: true, length: { maximum: 255 }
33
+ validates :sku_h_choice_name, length: { maximum: 255 }
34
+ validates :sku_v_choice_name, length: { maximum: 255 }
35
+ # TODO: add conditions (by limitless flag, backoder flag and etc..)
36
+ validates :quantity, numericality: { greater_than_or_equal_to: 0 }
37
+
38
+ delegate :name, to: :product
39
+ delegate :price, to: :product
40
+ delegate :sku_h_item_name, to: :product
41
+ delegate :sku_v_item_name, to: :product
42
+
43
+ ransack_options attribute_select: { associations: :product }, ransackable_attributes: { except: :product_id }
44
+
45
+ # 在庫の有無を取得する
46
+ #
47
+ # @example
48
+ # stock.quanaity = 1
49
+ # stock.stocked? #=> true
50
+ #
51
+ # @param quantity [Fixnum] 減算する在庫数を指定する
52
+ # @return [Boolean] 在庫があれば true を返す
53
+ # @see #unstocked?
54
+ def stocked?(quantity: 1)
55
+ (self.quantity - quantity) >= 0
56
+ end
57
+
58
+ # 在庫の有無を取得する
59
+ #
60
+ # @example
61
+ # stock.quanaity = 1
62
+ # stock.unstocked? #=> false
63
+ #
64
+ # @param quantity [Fixnum] 減算する在庫数を指定する
65
+ # @return [Boolean] {#stocked?} の逆。在庫がなければ true を返す
66
+ # @see #stocked?
67
+ def unstocked?(quantity: 1)
68
+ !stocked?(quantity: quantity)
69
+ end
70
+ end
71
+ 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
@@ -0,0 +1,30 @@
1
+ module Comable
2
+ class Store < ActiveRecord::Base
3
+ include Comable::Liquidable
4
+
5
+ belongs_to :theme, class_name: Comable::Theme.name
6
+
7
+ validates :name, length: { maximum: 255 }
8
+ validates :meta_keywords, length: { maximum: 255 }
9
+ validates :meta_description, length: { maximum: 255 }
10
+ validates :email, length: { maximum: 255 }
11
+
12
+ liquid_methods :name, :meta_keywords, :meta_description, :email
13
+
14
+ delegate :name, to: :theme, prefix: true, allow_nil: true
15
+
16
+ class << self
17
+ def instance
18
+ first || new(name: default_name)
19
+ end
20
+
21
+ def default_name
22
+ Comable.t('default_store_name')
23
+ end
24
+ end
25
+
26
+ def can_send_mail?
27
+ email.present?
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,25 @@
1
+ module Comable
2
+ class Theme < ActiveRecord::Base
3
+ has_one :store, class_name: Comable::Store.name
4
+
5
+ validates :name, uniqueness: { scope: :version }
6
+ validates :name, presence: true, length: { maximum: 255 }
7
+ validates :version, presence: true, length: { maximum: 255 }
8
+ validates :display, length: { maximum: 255 }
9
+ validates :description, length: { maximum: 255 }
10
+ validates :homepage, length: { maximum: 255 }
11
+ validates :author, length: { maximum: 255 }
12
+
13
+ def default_version
14
+ '0.1.0'
15
+ end
16
+
17
+ def to_param
18
+ name
19
+ end
20
+
21
+ def display_name
22
+ display.presence || name
23
+ end
24
+ end
25
+ end