comable_core 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +16 -4
  4. data/app/controllers/concerns/comable/permitted_attributes.rb +15 -0
  5. data/app/helpers/comable/application_helper.rb +36 -1
  6. data/app/helpers/comable/products_helper.rb +35 -8
  7. data/app/mailers/comable/order_mailer.rb +1 -1
  8. data/app/models/comable/ability.rb +18 -0
  9. data/app/models/comable/address.rb +6 -2
  10. data/app/models/comable/category.rb +72 -0
  11. data/app/models/comable/customer.rb +53 -53
  12. data/app/models/comable/image.rb +11 -0
  13. data/app/models/comable/order.rb +42 -47
  14. data/app/models/comable/order_detail.rb +30 -37
  15. data/app/models/comable/payment_method.rb +26 -0
  16. data/app/models/comable/product.rb +29 -3
  17. data/app/models/comable/shipment_method.rb +4 -0
  18. data/app/models/comable/stock.rb +8 -24
  19. data/app/models/comable/store.rb +7 -2
  20. data/{lib → app/models/concerns}/comable/cart_owner.rb +25 -11
  21. data/app/models/concerns/comable/checkout.rb +90 -0
  22. data/app/models/concerns/comable/product/search.rb +41 -0
  23. data/app/models/concerns/comable/role_owner.rb +15 -0
  24. data/app/uploaders/image_uploader.rb +7 -0
  25. data/app/views/comable/order_mailer/complete.text.erb +7 -9
  26. data/config/locales/ja.yml +237 -8
  27. data/db/migrate/20140120032559_create_comable_customers.rb +1 -4
  28. data/db/migrate/20140502060116_create_comable_stocks.rb +2 -3
  29. data/db/migrate/20140723175431_create_comable_orders.rb +4 -5
  30. data/db/migrate/20140723175810_create_comable_order_details.rb +3 -3
  31. data/db/migrate/20140817194104_create_comable_payment_methods.rb +11 -0
  32. data/db/migrate/20140926063541_create_comable_stores.rb +1 -1
  33. data/db/migrate/20141024025526_create_comable_addresses.rb +2 -2
  34. data/db/migrate/20150111031228_create_comable_categories.rb +9 -0
  35. data/db/migrate/20150111031229_create_comable_products_categories.rb +8 -0
  36. data/db/migrate/20150112173706_create_comable_images.rb +8 -0
  37. data/lib/comable/core/configuration.rb +6 -0
  38. data/lib/comable/core/engine.rb +23 -11
  39. data/lib/comable/errors.rb +0 -3
  40. data/lib/comable/{payment_method → payment_provider}/base.rb +1 -1
  41. data/lib/comable/{payment_method → payment_provider}/general.rb +1 -1
  42. data/lib/comable/{payment_method.rb → payment_provider.rb} +3 -3
  43. data/lib/comable/state_machine_patch.rb +16 -0
  44. data/lib/comable_core.rb +13 -3
  45. metadata +97 -10
  46. data/app/models/comable/order_delivery.rb +0 -21
  47. data/app/models/comable/payment.rb +0 -24
  48. data/db/migrate/20140723175624_create_comable_order_deliveries.rb +0 -9
  49. data/db/migrate/20140817194104_create_comable_payments.rb +0 -11
@@ -3,28 +3,29 @@ module Comable
3
3
  include Comable::SkuItem
4
4
  include Comable::SkuChoice
5
5
 
6
- belongs_to :stock, class_name: Comable::Stock.name, foreign_key: Comable::Stock.table_name.singularize.foreign_key
7
- belongs_to :order_delivery, class_name: Comable::OrderDelivery.name, foreign_key: Comable::OrderDelivery.table_name.singularize.foreign_key
6
+ belongs_to :stock, class_name: Comable::Stock.name, autosave: true
7
+ belongs_to :order, class_name: Comable::Order.name, inverse_of: :order_details
8
8
 
9
- accepts_nested_attributes_for :stock
10
-
11
- # TODO: バリデーションの追加
9
+ validates :quantity, numericality: { greater_than: 0 }
10
+ validate :valid_stock_quantity
12
11
 
13
12
  delegate :product, to: :stock
14
- delegate :guest_token, to: :order_delivery
15
- delegate :complete?, to: :order_delivery
16
- delegate :order, to: :order_delivery
13
+ delegate :image_url, to: :product
14
+ delegate :guest_token, to: :order
15
+ delegate :completed?, to: :order, allow_nil: true
16
+ delegate :completing?, to: :order, allow_nil: true
17
17
 
18
- before_save :save_to_add_cart, unless: :complete?
19
- before_save :verify_quantity, unless: :complete?
18
+ with_options if: -> { !completed? || completing? } do |incomplete|
19
+ incomplete.before_validation :copy_attributes
20
+ end
20
21
 
21
- def save_to_complete
22
- self.attributes = current_attributes
22
+ def complete
23
+ copy_attributes
23
24
  decrement_stock
24
25
  end
25
26
 
26
27
  # TODO: カート投入時との差額表示
27
- def save_to_add_cart
28
+ def copy_attributes
28
29
  self.attributes = current_attributes
29
30
  end
30
31
 
@@ -43,30 +44,30 @@ module Comable
43
44
  price * quantity
44
45
  end
45
46
 
46
- def valid_order_quantity?
47
- if quantity <= 0
48
- add_order_quantity_invalid_error_to_order
49
- return false
50
- end
51
-
52
- if stock.soldout?(quantity: quantity)
53
- add_product_soldout_error_to_order
54
- return false
47
+ def soldout_stock?
48
+ stock_with_clean_quantity do |stock|
49
+ stock.soldout?(quantity: quantity)
55
50
  end
51
+ end
56
52
 
57
- true
53
+ def valid_stock_quantity
54
+ return unless soldout_stock?
55
+ errors.add :quantity, Comable.t('errors.messages.product_soldout', name: stock.name_with_sku)
58
56
  end
59
57
 
60
58
  private
61
59
 
62
- def decrement_stock
63
- return unless quantity
64
- return unless stock.quantity
65
- stock.quantity -= quantity
60
+ def stock_with_clean_quantity
61
+ quantity_will = stock.quantity
62
+ stock.quantity = stock.quantity_was if stock.quantity_was
63
+ yield stock
64
+ ensure
65
+ stock.quantity = quantity_will
66
66
  end
67
67
 
68
- def verify_quantity
69
- fail Comable::NoStock if stock.soldout?(quantity: quantity)
68
+ def decrement_stock
69
+ stock.lock!
70
+ stock.quantity -= quantity
70
71
  end
71
72
 
72
73
  def current_attributes
@@ -80,13 +81,5 @@ module Comable
80
81
  sku_v_choice_name: stock.sku_v_choice_name
81
82
  }
82
83
  end
83
-
84
- def add_order_quantity_invalid_error_to_order
85
- order.errors.add :base, I18n.t('comable.errors.messages.order_quantity_invalid', name: stock.name_with_sku)
86
- end
87
-
88
- def add_product_soldout_error_to_order
89
- order.errors.add :base, I18n.t('comable.errors.messages.product_soldout', name: stock.name_with_sku)
90
- end
91
84
  end
92
85
  end
@@ -0,0 +1,26 @@
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 :enable_price_from, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
7
+ validates :enable_price_to, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
8
+
9
+ def payment_provider
10
+ return unless Object.const_defined?(payment_provider_type)
11
+ Object.const_get(payment_provider_type)
12
+ end
13
+
14
+ def payment_provider_name
15
+ payment_provider.display_name
16
+ end
17
+
18
+ def payment_provider_kind_key
19
+ payment_provider.kind.keys.slice(payment_provider_kind)
20
+ end
21
+
22
+ def payment_provider_kind_name
23
+ payment_provider.kind.slice(payment_provider_kind_key).values.first
24
+ end
25
+ end
26
+ end
@@ -1,18 +1,44 @@
1
1
  module Comable
2
2
  class Product < ActiveRecord::Base
3
3
  include Comable::SkuItem
4
+ include Comable::Product::Search
4
5
 
5
- has_many :stocks, class_name: Comable::Stock.name, foreign_key: table_name.singularize.foreign_key
6
- after_create :create_stock
6
+ has_many :stocks, class_name: Comable::Stock.name, dependent: :destroy
7
+ has_many :images, class_name: Comable::Image.name, dependent: :destroy
8
+ has_and_belongs_to_many :categories, class_name: Comable::Category.name, join_table: :comable_products_categories
9
+
10
+ accepts_nested_attributes_for :images, allow_destroy: true
11
+
12
+ validates :name, presence: true, length: { maximum: 255 }
13
+ validates :code, presence: true, length: { maximum: 255 }
14
+ validates :price, presence: true, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
15
+ validates :sku_h_item_name, length: { maximum: 255 }
16
+ validates :sku_v_item_name, length: { maximum: 255 }
17
+
18
+ # Add conditions for the images association.
19
+ # Override method of the images association to support Rails 3.x.
20
+ def images
21
+ super.order(:id)
22
+ end
23
+
24
+ def image_url
25
+ image = images.first
26
+ return image.url if image
27
+ 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTcxIiBoZWlnaHQ9IjE4MCIgdmlld0JveD0iMCAwIDE3MSAxODAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxkZWZzLz48cmVjdCB3aWR0aD0iMTcxIiBoZWlnaHQ9IjE4MCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9IjU4IiB5PSI5MCIgc3R5bGU9ImZpbGw6I0FBQUFBQTtmb250LXdlaWdodDpib2xkO2ZvbnQtZmFtaWx5OkFyaWFsLCBIZWx2ZXRpY2EsIE9wZW4gU2Fucywgc2Fucy1zZXJpZiwgbW9ub3NwYWNlO2ZvbnQtc2l6ZToxMHB0O2RvbWluYW50LWJhc2VsaW5lOmNlbnRyYWwiPjE3MXgxODA8L3RleHQ+PC9nPjwvc3ZnPg=='
28
+ end
7
29
 
8
30
  def unsold?
9
- stocks.activated.unsold.exists?
31
+ stocks.unsold.exists?
10
32
  end
11
33
 
12
34
  def soldout?
13
35
  !unsold?
14
36
  end
15
37
 
38
+ def category_path_names=(category_path_names, delimiter: Comable::Category::DEFAULT_PATH_NAME_DELIMITER)
39
+ self.categories = Comable::Category.find_by_path_names(category_path_names, delimiter: delimiter)
40
+ end
41
+
16
42
  private
17
43
 
18
44
  def create_stock
@@ -1,5 +1,9 @@
1
1
  module Comable
2
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
+
3
7
  scope :activated, -> { where(activate_flag: true) }
4
8
  scope :deactivated, -> { where(activate_flag: false) }
5
9
  end
@@ -6,16 +6,12 @@ module Comable
6
6
  class Stock < ActiveRecord::Base
7
7
  include Comable::SkuChoice
8
8
 
9
- belongs_to :product, class_name: Comable::Product.name, foreign_key: Comable::Product.table_name.singularize.foreign_key
9
+ belongs_to :product, class_name: Comable::Product.name
10
10
 
11
11
  #
12
12
  # @!group Scope
13
13
  #
14
14
 
15
- # @!scope class
16
- # 有効な在庫インスタンスを返す
17
- scope :activated, -> { where.not(product_id_num: nil) }
18
-
19
15
  # @!scope class
20
16
  # 品切れでない在庫インスタンスを返す
21
17
  scope :unsold, -> { where('quantity > ?', 0) }
@@ -28,6 +24,13 @@ module Comable
28
24
  # @!endgroup
29
25
  #
30
26
 
27
+ validates :product, presence: true
28
+ validates :code, presence: true, length: { maximum: 255 }
29
+ validates :sku_h_choice_name, length: { maximum: 255 }
30
+ validates :sku_v_choice_name, length: { maximum: 255 }
31
+ # TODO: add conditions (by limitless flag, backoder flag and etc..)
32
+ validates :quantity, numericality: { greater_than_or_equal_to: 0 }
33
+
31
34
  delegate :name, to: :product
32
35
  delegate :price, to: :product
33
36
  delegate :sku?, to: :product
@@ -41,8 +44,6 @@ module Comable
41
44
  # @return [Boolean] 在庫があれば true を返す
42
45
  # @see #soldout?
43
46
  def unsold?(quantity: 1)
44
- return false if product_id_num.nil?
45
- return false if self.quantity.nil?
46
47
  (self.quantity - quantity) >= 0
47
48
  end
48
49
 
@@ -57,22 +58,5 @@ module Comable
57
58
  def soldout?(quantity: 1)
58
59
  !unsold?(quantity: quantity)
59
60
  end
60
-
61
- # 在庫減算を行う
62
- #
63
- # @example
64
- # stock.quantity #=> 10
65
- # stock.decrement!(quantity: 1) #=> true
66
- # stock.quantity #=> 9
67
- #
68
- # @param quantity [Fixnum] 減算する在庫数を指定する
69
- # @return [Boolean] レコードの保存に成功すると true を返す
70
- def decrement!(quantity: 1)
71
- with_lock do
72
- # TODO: カラムマッピングのdecrementメソッドへの対応
73
- self.quantity -= quantity
74
- save!
75
- end
76
- end
77
61
  end
78
62
  end
@@ -1,11 +1,16 @@
1
1
  module Comable
2
2
  class Store < ActiveRecord::Base
3
+ validates :name, length: { maximum: 255 }
4
+ validates :meta_keywords, length: { maximum: 255 }
5
+ validates :meta_description, length: { maximum: 255 }
6
+ validates :email_sender, length: { maximum: 255 }
7
+
3
8
  class << self
4
9
  def instance
5
- first || new(name: default_store_name)
10
+ first || new(name: default_name)
6
11
  end
7
12
 
8
- def default_store_name
13
+ def default_name
9
14
  'Comable store'
10
15
  end
11
16
  end
@@ -32,6 +32,21 @@ module Comable
32
32
  def price
33
33
  sum(&:current_subtotal_price)
34
34
  end
35
+
36
+ def count
37
+ sum(&:quantity)
38
+ end
39
+
40
+ alias_method :size, :count
41
+
42
+ # TODO: Refactoring
43
+ def errors
44
+ ActiveModel::Errors.new(self).tap do |obj|
45
+ map(&:errors).map(&:full_messages).flatten.each do |full_message|
46
+ obj[:base] << full_message
47
+ end
48
+ end
49
+ end
35
50
  end
36
51
 
37
52
  private
@@ -50,31 +65,30 @@ module Comable
50
65
  end
51
66
 
52
67
  def add_stock_to_cart(stock, quantity)
53
- cart_items = find_cart_items_by(stock)
54
- if cart_items.any?
55
- cart_item = cart_items.first
68
+ cart_item = find_cart_item_by(stock)
69
+ if cart_item
56
70
  cart_item.quantity += quantity
57
71
  (cart_item.quantity > 0) ? cart_item.save : cart_item.destroy
58
72
  else
59
- cart_items.create(quantity: quantity)
73
+ cart_items.build(stock_id: stock.id, quantity: quantity).save
60
74
  end
61
75
  end
62
76
 
63
77
  def reset_stock_from_cart(stock, quantity)
64
- cart_items = find_cart_items_by(stock)
78
+ cart_item = find_cart_item_by(stock)
65
79
  if quantity > 0
66
- return add_stock_to_cart(stock, quantity) if cart_items.empty?
67
- cart_items.first.update_attributes(quantity: quantity)
80
+ return add_stock_to_cart(stock, quantity) unless cart_item
81
+ cart_item.update_attributes(quantity: quantity)
68
82
  else
69
- return false if cart_items.empty?
70
- cart_items.first.destroy
83
+ return false unless cart_item
84
+ cart_items.destroy(cart_item)
71
85
  end
72
86
  end
73
87
 
74
- def find_cart_items_by(stock)
88
+ def find_cart_item_by(stock)
75
89
  # TODO: Refactoring
76
90
  fail unless stock.is_a?(Comable::Stock)
77
- cart_items.where(Comable::Stock.table_name.singularize.foreign_key => stock.id)
91
+ cart_items.find { |cart_item| cart_item.stock.id == stock.id }
78
92
  end
79
93
  end
80
94
  end
@@ -0,0 +1,90 @@
1
+ module Comable
2
+ module Checkout
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ state_machine initial: :cart do
7
+ state :cart
8
+ state :orderer
9
+ state :delivery
10
+ state :shipment
11
+ state :payment
12
+ state :confirm
13
+ state :complete
14
+
15
+ event :next_state do
16
+ transition :cart => :orderer, if: :orderer_required?
17
+ transition [:cart, :orderer] => :delivery, if: :delivery_required?
18
+ transition [:cart, :orderer, :delivery] => :shipment, if: :shipment_required?
19
+ transition [:cart, :orderer, :delivery, :shipment] => :payment, if: :payment_required?
20
+ transition all - [:confirm, :complete] => :confirm
21
+ transition :confirm => :complete
22
+ end
23
+
24
+ before_transition to: :complete do |order, _transition|
25
+ order.complete
26
+ 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
+
39
+ with_options if: -> { stated?(:orderer) } do |context|
40
+ context.validates :bill_address, presence: true
41
+ end
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
50
+
51
+ with_options if: -> { stated?(:shipment) && shipment_required? } do |context|
52
+ context.validates :shipment_method, presence: true
53
+ end
54
+
55
+ with_options if: -> { stated?(:complete) } do |context|
56
+ context.validates :code, presence: true
57
+ context.validates :shipment_fee, presence: true
58
+ context.validates :total_price, presence: true
59
+ end
60
+ end
61
+
62
+ module ClassMethods
63
+ def state_names
64
+ state_machine.states.keys
65
+ end
66
+ end
67
+
68
+ def stated?(target_state)
69
+ target_state_index = self.class.state_names.index(target_state.to_sym)
70
+ current_state_index = self.class.state_names.index(state_name)
71
+ target_state_index < current_state_index
72
+ end
73
+
74
+ def orderer_required?
75
+ bill_address.nil? || bill_address.new_record?
76
+ end
77
+
78
+ def delivery_required?
79
+ ship_address.nil? || ship_address.new_record?
80
+ end
81
+
82
+ def payment_required?
83
+ Comable::PaymentMethod.exists?
84
+ end
85
+
86
+ def shipment_required?
87
+ Comable::ShipmentMethod.activated.exists?
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,41 @@
1
+ module Comable
2
+ class Product
3
+ module Search
4
+ extend ActiveSupport::Concern
5
+
6
+ SEARCH_COLUMNS = %i( code name caption )
7
+
8
+ module ClassMethods
9
+ def search(query)
10
+ keywords = parse_to_keywords(query)
11
+ return (Rails::VERSION::MAJOR == 3) ? scoped : all if keywords.empty?
12
+ where(keywords_to_arel(keywords))
13
+ end
14
+
15
+ private
16
+
17
+ def keywords_to_arel(keywords)
18
+ keywords.inject(nil) do |arel_chain, keyword|
19
+ arel = keyword_to_arel(keyword)
20
+ arel_chain ? arel_chain.and(arel) : arel
21
+ end
22
+ end
23
+
24
+ def keyword_to_arel(keyword)
25
+ SEARCH_COLUMNS.inject(nil) do |arel_chain, column|
26
+ arel = arel_table[column].matches("%#{keyword}%")
27
+ arel_chain ? arel_chain.or(arel) : arel
28
+ end
29
+ end
30
+
31
+ def parse_to_keywords(query)
32
+ return [] if query.blank?
33
+ query
34
+ .delete('%')
35
+ .tr(' ', ' ')
36
+ .split(' ')
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,15 @@
1
+ module Comable
2
+ module RoleOwner
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ extend Enumerize
7
+
8
+ enumerize :role, in: %i(
9
+ admin
10
+ reporter
11
+ customer
12
+ ), default: :customer, predicates: true
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ class ImageUploader < CarrierWave::Uploader::Base
2
+ storage :file
3
+
4
+ def store_dir
5
+ "#{model.class.to_s.underscore}/#{model.id}"
6
+ end
7
+ end
@@ -2,9 +2,9 @@
2
2
  <%= "#{@order.class.human_attribute_name(:code)}: #{@order.code}" %>
3
3
  ----------------------------------------------------------------------
4
4
 
5
- <%= I18n.t('comable.order_mailer.complete.dear', name: @order.full_name) %>
5
+ <%= Comable.t('order_mailer.complete.dear', name: @order.bill_full_name) %>
6
6
 
7
- <%= I18n.t('comable.order_mailer.complete.introductions', store_name: current_store.name) %>
7
+ <%= Comable.t('order_mailer.complete.introductions', store_name: current_store.name) %>
8
8
 
9
9
  <%- shipment_method = @order.shipment_method %>
10
10
  <%- if shipment_method %>
@@ -12,10 +12,8 @@
12
12
  <%= shipment_method.name %>
13
13
  <%- end %>
14
14
 
15
- <%= Comable::OrderDelivery.model_name.human %>:
16
- <%- @order.order_deliveries.each do |order_delivery| %>
17
- <%= name_with_honorific order_delivery.full_name %>
18
- <%- end %>
15
+ <%= @order.class.human_attribute_name(:ship_address) %>:
16
+ <%= name_with_honorific @order.ship_full_name %>
19
17
 
20
18
  ======================================================================
21
19
 
@@ -24,7 +22,7 @@
24
22
  <%= "#{@order.class.human_attribute_name(:code)}: #{@order.code}" %>
25
23
  <%= "#{@order.class.human_attribute_name(:completed_at)}: #{I18n.l @order.completed_at.to_date}" %>
26
24
 
27
- <%- @order.order_deliveries.map(&:order_details).flatten.each do |order_detail| %>
25
+ <%- @order.order_details.each do |order_detail| %>
28
26
  <%= name_with_quantity order_detail.name_with_sku, order_detail.quantity %>
29
27
  <%= number_to_currency order_detail.subtotal_price %>
30
28
 
@@ -36,8 +34,8 @@
36
34
 
37
35
  <%= "#{@order.class.human_attribute_name(:total_price)}: #{number_to_currency @order.total_price}" %>
38
36
 
39
- <%= "#{@order.class.human_attribute_name(:payment)}: #{@order.payment.name}\n" if @order.payment -%>
37
+ <%= "#{@order.class.human_attribute_name(:payment_method)}: #{@order.payment_method.name}\n" if @order.payment_method -%>
40
38
 
41
39
  ======================================================================
42
40
 
43
- <%= I18n.t('comable.order_mailer.complete.outroductions', store_name: current_store.name) %>
41
+ <%= Comable.t('order_mailer.complete.outroductions', store_name: current_store.name) %>