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,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