comable-core 0.7.0.beta1 → 0.7.0.beta2

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +7 -2
  3. data/app/controllers/concerns/comable/permitted_attributes.rb +1 -0
  4. data/app/helpers/comable/application_helper.rb +4 -0
  5. data/app/models/comable/inventory/adjuster.rb +40 -0
  6. data/app/models/comable/inventory/coordinator.rb +56 -0
  7. data/app/models/comable/inventory/package.rb +47 -0
  8. data/app/models/comable/inventory/packer.rb +25 -0
  9. data/app/models/comable/inventory/unit.rb +22 -0
  10. data/app/models/comable/navigation.rb +2 -0
  11. data/app/models/comable/navigation_item.rb +29 -6
  12. data/app/models/comable/order/associations.rb +2 -2
  13. data/app/models/comable/order/deprecated_methods.rb +27 -0
  14. data/app/models/comable/order/validations.rb +1 -1
  15. data/app/models/comable/order.rb +25 -11
  16. data/app/models/comable/order_item.rb +12 -40
  17. data/app/models/comable/page.rb +3 -3
  18. data/app/models/comable/payment_method.rb +2 -0
  19. data/app/models/comable/product.rb +16 -12
  20. data/app/models/comable/shipment.rb +26 -5
  21. data/app/models/comable/shipment_item.rb +47 -0
  22. data/app/models/comable/shipment_method.rb +1 -0
  23. data/app/models/comable/stock.rb +13 -9
  24. data/app/models/comable/stock_location.rb +29 -0
  25. data/app/models/comable/theme.rb +2 -0
  26. data/app/models/comable/tracker.rb +3 -2
  27. data/app/models/comable/user.rb +1 -0
  28. data/app/models/comable/variant/quantifier.rb +27 -0
  29. data/app/models/comable/variant.rb +25 -12
  30. data/app/models/concerns/comable/cart_owner.rb +1 -5
  31. data/app/models/concerns/comable/checkout.rb +4 -7
  32. data/app/models/concerns/comable/linkable.rb +11 -22
  33. data/app/models/concerns/comable/product/search.rb +1 -1
  34. data/app/views/comable/order_mailer/complete.text.erb +2 -3
  35. data/config/locales/en.yml +14 -0
  36. data/config/locales/ja.yml +14 -0
  37. data/db/migrate/20150918065115_add_property_to_comable_products.rb +5 -0
  38. data/db/migrate/20150924010143_create_comable_stock_locations.rb +11 -0
  39. data/db/migrate/20150924102640_add_stock_location_id_to_comable_stocks.rb +10 -0
  40. data/db/migrate/20150924111838_add_stock_location_id_to_comable_shipments.rb +7 -0
  41. data/db/migrate/20150924114017_set_default_stock_location.rb +28 -0
  42. data/db/migrate/20151012143215_create_comable_shipment_items.rb +11 -0
  43. data/db/migrate/20151013082845_remove_null_option_of_shipment_method_id_on_comable_shipments.rb +10 -0
  44. data/db/migrate/20151013194926_add_guest_token_index_to_comable_orders.rb +5 -0
  45. metadata +20 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bfeeb810107eafe21ff7ccc16a8796708892aa08
4
- data.tar.gz: af72df7aebb8d185f96c36a9c53ad4ca3a7d769f
3
+ metadata.gz: 324ed7d3cdee480e0d7b0529fd7a90195cc69a37
4
+ data.tar.gz: 487980666fa2ccbfc92028700433a741eb610afb
5
5
  SHA512:
6
- metadata.gz: 2b8ad2b68377430abf27f0113075d2ca0771d51b4377765e87663c6e52b63309f39a4b2ad2f59823a0dd23d513ad2763f307a5cc8401b581b7d2139ea4c4ea43
7
- data.tar.gz: 909ec7862a42e7f29977abedc6eb1f9af4e99c22298469525c1ae95bac369b82d3e0462a65c01a01d2d51c259067f633200a71c457d4fc90fd65df154441d11c
6
+ metadata.gz: 24bb175945a7065c8589e02f665e420ae56823c69bea0472ac27194a9abcc70675acfcbfa20eb3028f3e4826c814080bde8d85a97f5b226f544b094a81d235b6
7
+ data.tar.gz: 8e6a2a6ca8dc65d329c985ed4f01415da7b6fe5a01d4e78c4688aa2122b9a5252f8e3cb0f1244d9a5dd439172408de351b43e97cdfb15479e968ad412bf4916b
data/Rakefile CHANGED
@@ -4,6 +4,7 @@ rescue LoadError
4
4
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
5
  end
6
6
 
7
+ require 'rspec/core/rake_task'
7
8
  require 'rdoc/task'
8
9
 
9
10
  RDoc::Task.new(:rdoc) do |rdoc|
@@ -69,9 +70,9 @@ if File.exist?('comable.gemspec')
69
70
  end
70
71
  end
71
72
 
72
- task default: ['app:spec:all', 'rubocop', 'brakeman:all']
73
+ task default: ['app:spec:all', 'jasmine', 'rubocop', 'brakeman:all']
73
74
  else
74
- task default: ['app:spec', 'rubocop', 'brakeman']
75
+ task default: ['app:spec', 'jasmine', 'rubocop', 'brakeman']
75
76
  end
76
77
 
77
78
  Bundler::GemHelper.install_tasks
@@ -79,6 +80,10 @@ Bundler::GemHelper.install_tasks
79
80
  # from https://github.com/rspec/rspec-rails/issues/936
80
81
  task 'test:prepare'
81
82
 
83
+ task :jasmine do
84
+ sh 'bundle exec rake app:spec:javascript RAILS_ENV=test'
85
+ end
86
+
82
87
  task :rubocop do
83
88
  sh 'rubocop'
84
89
  end
@@ -2,6 +2,7 @@ module Comable
2
2
  module PermittedAttributes
3
3
  def permitted_address_attributes
4
4
  [
5
+ :id,
5
6
  :family_name,
6
7
  :first_name,
7
8
  :zip_code,
@@ -65,6 +65,10 @@ module Comable
65
65
  ).stringify_keys
66
66
  end
67
67
 
68
+ def page_name
69
+ [controller_name, action_name].join(':')
70
+ end
71
+
68
72
  private
69
73
 
70
74
  def comable_root_path
@@ -0,0 +1,40 @@
1
+ module Comable
2
+ module Inventory
3
+ class Adjuster
4
+ attr_accessor :packages
5
+ attr_accessor :units
6
+
7
+ def initialize(packages, units)
8
+ @packages = packages.map(&:clone)
9
+ @units = units
10
+ end
11
+
12
+ def adjusted_packages
13
+ remove_duplicated_items
14
+ packages
15
+ end
16
+
17
+ private
18
+
19
+ def remove_duplicated_items
20
+ units.each do |unit|
21
+ remove_duplicated(unit)
22
+ end
23
+ end
24
+
25
+ def remove_duplicated(unit)
26
+ duplicated = false
27
+
28
+ packages.each do |package|
29
+ next unless package.find(unit)
30
+
31
+ if duplicated
32
+ package.remove(unit)
33
+ else
34
+ duplicated = true
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,56 @@
1
+ module Comable
2
+ module Inventory
3
+ class Coordinator
4
+ attr_accessor :order
5
+ attr_accessor :units
6
+
7
+ def initialize(order)
8
+ @order = order
9
+ @units = build_units
10
+ end
11
+
12
+ def shipments
13
+ packages.map(&:to_shipment)
14
+ end
15
+
16
+ private
17
+
18
+ def packages
19
+ packages = build_packages
20
+ adjusted_packages = adjust_packages(packages)
21
+ compact_packages(adjusted_packages)
22
+ end
23
+
24
+ def build_packages
25
+ Comable::StockLocation.active.map do |stock_location|
26
+ next unless units_exists_in? stock_location
27
+ build_packer(stock_location).package
28
+ end.compact
29
+ end
30
+
31
+ def adjust_packages(packages)
32
+ Adjuster.new(packages, units).adjusted_packages
33
+ end
34
+
35
+ def compact_packages(packages)
36
+ packages.reject(&:empty?)
37
+ end
38
+
39
+ def units_exists_in?(stock_location)
40
+ stock_location.stocks.where(variant_id: units.map(&:variant).map(&:id).uniq).exists?
41
+ end
42
+
43
+ def build_packer(stock_location)
44
+ Packer.new(stock_location, units)
45
+ end
46
+
47
+ def build_units
48
+ order.order_items.map do |order_item|
49
+ order_item.quantity.times.map do
50
+ Unit.new(order_item.variant)
51
+ end
52
+ end.flatten
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,47 @@
1
+ module Comable
2
+ module Inventory
3
+ class Package
4
+ attr_accessor :stock_location
5
+ attr_accessor :units
6
+
7
+ delegate :empty?, :size, :count, to: :units
8
+
9
+ def initialize(stock_location)
10
+ @stock_location = stock_location
11
+ @units = []
12
+ end
13
+
14
+ def initialize_copy(package)
15
+ super
16
+ self.units = package.units.clone
17
+ end
18
+
19
+ def to_shipment
20
+ shipment = Comable::Shipment.new(stock_location: stock_location)
21
+ shipment.shipment_items = build_shipment_items(shipment)
22
+ shipment
23
+ end
24
+
25
+ def find(unit)
26
+ units.detect { |u| u == unit }
27
+ end
28
+
29
+ def add(unit)
30
+ unit = [unit] unless unit.is_a? Array
31
+ units.concat(unit)
32
+ end
33
+
34
+ def remove(unit)
35
+ units.delete(unit)
36
+ end
37
+
38
+ private
39
+
40
+ def build_shipment_items(shipment)
41
+ units.map do |unit|
42
+ unit.to_shipment_item(shipment)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,25 @@
1
+ module Comable
2
+ module Inventory
3
+ class Packer
4
+ attr_accessor :stock_location
5
+ attr_accessor :units
6
+
7
+ def initialize(stock_location, units)
8
+ @stock_location = stock_location
9
+ @units = units
10
+ end
11
+
12
+ def package
13
+ package = Package.new(stock_location)
14
+
15
+ units.group_by(&:variant).each do |variant, variant_units|
16
+ stock = stock_location.find_stock_item(variant)
17
+ next unless stock
18
+ package.add variant_units.take(stock.quantity) if stock.stocked?
19
+ end
20
+
21
+ package
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ module Comable
2
+ module Inventory
3
+ class Unit
4
+ attr_accessor :variant
5
+
6
+ def initialize(variant)
7
+ @variant = variant
8
+ end
9
+
10
+ def to_shipment_item(shipment)
11
+ stock = find_stock_item(shipment)
12
+ Comable::ShipmentItem.new(stock: stock)
13
+ end
14
+
15
+ private
16
+
17
+ def find_stock_item(shipment)
18
+ shipment.stock_location.find_stock_item(variant)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -8,5 +8,7 @@ module Comable
8
8
 
9
9
  validates :name, length: { maximum: 255 }, presence: true
10
10
  validates :navigation_items, presence: true
11
+
12
+ scope :by_newest, -> { reorder(created_at: :desc) }
11
13
  end
12
14
  end
@@ -1,5 +1,7 @@
1
1
  module Comable
2
2
  class NavigationItem < ActiveRecord::Base
3
+ include Comable::Linkable
4
+
3
5
  belongs_to :navigation
4
6
  belongs_to :linkable, polymorphic: true
5
7
 
@@ -12,7 +14,6 @@ module Comable
12
14
  validates :position, uniqueness: { scope: :navigation_id }
13
15
 
14
16
  class << self
15
- # TODO: Refactor methods and modules for linkable
16
17
  def linkable_params_lists
17
18
  [
18
19
  web_address_linkable_params, # Web Address
@@ -21,26 +22,40 @@ module Comable
21
22
  ].compact
22
23
  end
23
24
 
25
+ def linkable_id_options(type)
26
+ params = linkable_params(type)
27
+ params ? params[:linkable_id_options] : [[]]
28
+ end
29
+
30
+ private
31
+
32
+ def linkable_params(type)
33
+ linkable_params_lists.find do |params|
34
+ params[:type].to_s == type.to_s
35
+ end
36
+ end
37
+
24
38
  def web_address_linkable_params
25
39
  {
26
40
  type: nil,
27
- name: Comable.t('admin.nav.navigation_items.web_address')
41
+ name: Comable.t('admin.nav.navigation_items.web_address'),
42
+ linkable_id_options: [[]]
28
43
  }
29
44
  end
30
45
 
31
46
  def product_linkable_params
32
- return unless Comable::Product.linkable_exists?
33
47
  {
34
48
  type: Comable::Product.to_s,
35
- name: Comable.t('products')
49
+ name: Comable.t('products'),
50
+ linkable_id_options: calc_linkable_id_options(Comable::Product, use_index: true)
36
51
  }
37
52
  end
38
53
 
39
54
  def page_linkable_params
40
- return unless Comable::Page.linkable_exists?
41
55
  {
42
56
  type: Comable::Page.to_s,
43
- name: Comable.t('pages')
57
+ name: Comable.t('pages'),
58
+ linkable_id_options: calc_linkable_id_options(Comable::Page, name: :title)
44
59
  }
45
60
  end
46
61
  end
@@ -48,5 +63,13 @@ module Comable
48
63
  def linkable_class
49
64
  linkable_type.constantize if linkable_type.present?
50
65
  end
66
+
67
+ def linkable_id_options
68
+ self.class.linkable_id_options(linkable_type)
69
+ end
70
+
71
+ def linkable_exists?
72
+ linkable_id_options.all?(&:present?)
73
+ end
51
74
  end
52
75
  end
@@ -9,13 +9,13 @@ module Comable
9
9
  belongs_to :ship_address, class_name: Comable::Address.name, autosave: true, dependent: :destroy
10
10
  has_many :order_items, dependent: :destroy, class_name: Comable::OrderItem.name, inverse_of: :order
11
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
12
+ has_many :shipments, dependent: :destroy, class_name: Comable::Shipment.name, inverse_of: :order
13
13
 
14
14
  accepts_nested_attributes_for :bill_address
15
15
  accepts_nested_attributes_for :ship_address
16
16
  accepts_nested_attributes_for :order_items
17
17
  accepts_nested_attributes_for :payment
18
- accepts_nested_attributes_for :shipment
18
+ accepts_nested_attributes_for :shipments
19
19
  end
20
20
  end
21
21
  end
@@ -0,0 +1,27 @@
1
+ module Comable
2
+ class Order < ActiveRecord::Base
3
+ module DeprecatedMethods
4
+ extend ActiveSupport::Concern
5
+
6
+ def shipment
7
+ shipments.first
8
+ end
9
+
10
+ def shipment=(shipment)
11
+ shipments << shipment unless shipments.include? shipment
12
+ end
13
+
14
+ included do
15
+ delegate :state, :human_state_name, to: :shipment, allow_nil: true, prefix: true
16
+
17
+ #
18
+ # Deprecated methods
19
+ #
20
+ deprecate :shipment, deprecator: Comable::Deprecator.instance
21
+ deprecate :shipment=, deprecator: Comable::Deprecator.instance
22
+ deprecate :shipment_state, deprecator: Comable::Deprecator.instance
23
+ deprecate :shipment_human_state_name, deprecator: Comable::Deprecator.instance
24
+ end
25
+ end
26
+ end
27
+ end
@@ -20,7 +20,7 @@ module Comable
20
20
  end
21
21
 
22
22
  with_options if: -> { stated?(:shipment) && shipment_required? } do |context|
23
- context.validates :shipment, presence: true
23
+ context.validates :shipments, presence: true
24
24
  end
25
25
 
26
26
  with_options if: -> { stated?(:payment) && payment_required? } do |context|
@@ -3,6 +3,7 @@ require_dependency 'comable/order/callbacks'
3
3
  require_dependency 'comable/order/scopes'
4
4
  require_dependency 'comable/order/validations'
5
5
  require_dependency 'comable/order/morrisable'
6
+ require_dependency 'comable/order/deprecated_methods'
6
7
 
7
8
  module Comable
8
9
  class Order < ActiveRecord::Base
@@ -14,15 +15,15 @@ module Comable
14
15
  include Comable::Order::Scopes
15
16
  include Comable::Order::Validations
16
17
  include Comable::Order::Morrisable
18
+ include Comable::Order::DeprecatedMethods
17
19
 
18
- ransack_options attribute_select: { associations: [:payment, :shipment] }, ransackable_attributes: { except: [:bill_address_id, :ship_address_id] }
20
+ ransack_options attribute_select: { associations: [:payment, :shipments] }, ransackable_attributes: { except: [:bill_address_id, :ship_address_id] }
19
21
 
20
22
  liquid_methods :code, :payment_fee, :shipment_fee, :item_total_price, :total_price, :order_items
21
23
 
22
24
  delegate :full_name, to: :bill_address, allow_nil: true, prefix: :bill
23
25
  delegate :full_name, to: :ship_address, allow_nil: true, prefix: :ship
24
26
  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
  delegate :cancel!, :resume!, to: :payment, allow_nil: true, prefix: true
27
28
 
28
29
  def complete!
@@ -34,7 +35,7 @@ module Comable
34
35
  save!
35
36
 
36
37
  payment.next_state! if payment
37
- shipment.next_state! if shipment
38
+ shipments.each(&:next_state!)
38
39
 
39
40
  touch(:completed_at)
40
41
  end
@@ -45,16 +46,24 @@ module Comable
45
46
  deprecate :complete, deprecator: Comable::Deprecator.instance
46
47
 
47
48
  def restock!
48
- order_items.each(&:restock)
49
- save!
49
+ shipments.each(&:restock!)
50
50
  end
51
51
 
52
52
  def unstock!
53
- order_items.each(&:unstock)
53
+ shipments.each(&:unstock!)
54
+ end
55
+
56
+ def assign_inventory_units_to_shipments
57
+ reset_shipments
58
+ self.shipments = Comable::Inventory::Coordinator.new(self).shipments
54
59
  save!
55
60
  end
56
61
 
57
- def stocked_items
62
+ def reset_shipments
63
+ shipments.destroy_all
64
+ end
65
+
66
+ def unstocked_items
58
67
  order_items.to_a.select(&:unstocked?)
59
68
  end
60
69
 
@@ -70,7 +79,7 @@ module Comable
70
79
 
71
80
  # 時価送料を取得
72
81
  def current_shipment_fee
73
- shipment.try(:fee) || 0
82
+ shipments.to_a.sum(&:fee)
74
83
  end
75
84
 
76
85
  # Get the current payment fee
@@ -88,7 +97,7 @@ module Comable
88
97
  self.bill_address ||= order.bill_address
89
98
  self.ship_address ||= order.ship_address
90
99
  self.payment ||= order.payment
91
- self.shipment ||= order.shipment
100
+ self.shipments = order.shipments if shipments.empty?
92
101
 
93
102
  stated?(order.state) ? save! : next_state!
94
103
  end
@@ -102,11 +111,16 @@ module Comable
102
111
  end
103
112
 
104
113
  def shipped?
105
- shipment ? shipment.completed? : true
114
+ return true if shipments.empty?
115
+ shipments.all?(&:completed?)
106
116
  end
107
117
 
108
118
  def can_ship?
109
- shipment && shipment.ready? && paid? && completed?
119
+ shipments.any?(&:can_ship?)
120
+ end
121
+
122
+ def ship!
123
+ shipments.with_state(:ready).each(&:ship!)
110
124
  end
111
125
 
112
126
  private
@@ -14,8 +14,7 @@ module Comable
14
14
 
15
15
  liquid_methods :name, :name_with_sku, :code, :quantity, :price, :subtotal_price
16
16
 
17
- delegate :stock, to: :variant
18
- delegate :product, to: :stock
17
+ delegate :product, to: :variant
19
18
  delegate :image_url, to: :product
20
19
  delegate :guest_token, to: :order
21
20
  delegate :completed?, to: :order, allow_nil: true
@@ -23,15 +22,7 @@ module Comable
23
22
  before_validation :copy_attributes, unless: :completed?
24
23
 
25
24
  def complete
26
- unstock
27
- end
28
-
29
- def unstock
30
- decrement_stock
31
- end
32
-
33
- def restock
34
- increment_stock
25
+ # Nothing to do
35
26
  end
36
27
 
37
28
  # TODO: カート投入時との差額表示
@@ -41,7 +32,7 @@ module Comable
41
32
 
42
33
  # 時価を取得
43
34
  def current_price
44
- stock.price
35
+ variant.price
45
36
  end
46
37
 
47
38
  # 時価小計を取得
@@ -55,9 +46,7 @@ module Comable
55
46
  end
56
47
 
57
48
  def unstocked?
58
- stock_with_clean_quantity do |stock|
59
- stock.unstocked?(quantity: quantity)
60
- end
49
+ !variant.can_supply? quantity
61
50
  end
62
51
 
63
52
  def sku_h_item_name
@@ -76,18 +65,19 @@ module Comable
76
65
  variant.option_values.second.try(:name)
77
66
  end
78
67
 
68
+ def stock
69
+ variant.stocks.first
70
+ end
71
+
79
72
  def stock=(stock)
80
- if variant
81
- variant.stock = stock
82
- else
83
- build_variant(stock: stock)
84
- end
73
+ self.variant = stock.variant || stock.build_variant
85
74
  end
86
75
 
87
76
  #
88
77
  # Deprecated methods
89
78
  #
90
79
  deprecate :stock, deprecator: Comable::Deprecator.instance
80
+ deprecate :stock=, deprecator: Comable::Deprecator.instance
91
81
  deprecate :sku_h_item_name, deprecator: Comable::Deprecator.instance
92
82
  deprecate :sku_v_item_name, deprecator: Comable::Deprecator.instance
93
83
  deprecate :sku_h_choice_name, deprecator: Comable::Deprecator.instance
@@ -100,28 +90,10 @@ module Comable
100
90
  errors.add :quantity, Comable.t('errors.messages.out_of_stock', name: stock.name_with_sku)
101
91
  end
102
92
 
103
- def stock_with_clean_quantity
104
- quantity_will = stock.quantity
105
- stock.quantity = stock.quantity_was if stock.quantity_was
106
- yield stock
107
- ensure
108
- stock.quantity = quantity_will
109
- end
110
-
111
- def decrement_stock
112
- stock.lock!
113
- stock.quantity -= quantity
114
- end
115
-
116
- def increment_stock
117
- stock.lock!
118
- stock.quantity += quantity
119
- end
120
-
121
93
  def current_attributes
122
94
  {
123
- name: stock.name,
124
- price: stock.price,
95
+ name: variant.name,
96
+ price: variant.price,
125
97
  sku: variant.sku
126
98
  }
127
99
  end
@@ -1,10 +1,10 @@
1
1
  module Comable
2
2
  class Page < ActiveRecord::Base
3
3
  include Comable::Ransackable
4
- include Comable::Linkable
5
4
  extend FriendlyId
6
5
 
7
- linkable_columns_keys name: :title
6
+ PREVIEW_SESSION_KEY = :preview_page
7
+
8
8
  friendly_id :title, use: :slugged
9
9
 
10
10
  validates :title, length: { maximum: 255 }, presence: true
@@ -14,7 +14,7 @@ module Comable
14
14
  validates :meta_keywords, length: { maximum: 255 }
15
15
  validates :slug, length: { maximum: 255 }, presence: true, uniqueness: true
16
16
 
17
- PREVIEW_SESSION_KEY = :preview_page
17
+ scope :by_newest, -> { reorder(created_at: :desc) }
18
18
 
19
19
  def published?
20
20
  published_at.present? && published_at <= Time.now
@@ -7,6 +7,8 @@ module Comable
7
7
  validates :enable_price_from, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
8
8
  validates :enable_price_to, numericality: { greater_than_or_equal_to: 0, allow_blank: true }
9
9
 
10
+ scope :by_newest, -> { reorder(created_at: :desc) }
11
+
10
12
  def payment_provider
11
13
  return unless Object.const_defined?(payment_provider_type)
12
14
  Object.const_get(payment_provider_type)