stall 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -21
- data/app/assets/javascripts/para/stall/inputs/variants-matrix/input.coffee +8 -1
- data/app/assets/javascripts/para/stall/inputs/variants-matrix/variant.coffee +9 -0
- data/app/assets/javascripts/stall.coffee +7 -1
- data/app/assets/javascripts/stall/add-to-cart-form.coffee +1 -4
- data/app/assets/javascripts/stall/products-filters.coffee +29 -0
- data/app/assets/stylesheets/para/stall.sass +5 -0
- data/app/assets/stylesheets/stall.sass +0 -0
- data/app/controllers/stall/checkout/steps_controller.rb +6 -5
- data/app/controllers/stall/checkout_base_controller.rb +14 -0
- data/app/controllers/stall/checkouts_controller.rb +7 -4
- data/app/controllers/stall/curated_product_lists_controller.rb +10 -0
- data/app/controllers/stall/line_items_controller.rb +1 -5
- data/app/controllers/stall/manufacturers_controller.rb +12 -0
- data/app/controllers/stall/omniauth_callbacks_controller.rb +49 -0
- data/app/controllers/stall/product_categories_controller.rb +13 -0
- data/app/controllers/stall/products_breadcrumbs.rb +16 -0
- data/app/controllers/stall/products_controller.rb +20 -0
- data/app/controllers/stall/products_search.rb +11 -0
- data/app/helpers/stall/customers_helper.rb +0 -10
- data/app/helpers/stall/omniauth_helper.rb +7 -0
- data/app/helpers/stall/prices_helper.rb +12 -0
- data/app/helpers/stall/products_filters_helper.rb +34 -0
- data/app/mailers/stall/customer_mailer.rb +4 -3
- data/app/models/curated_list_product.rb +3 -0
- data/app/models/curated_product_list.rb +3 -0
- data/app/models/image.rb +3 -0
- data/app/models/product_suggestion.rb +3 -0
- data/app/models/stall/models/curated_list_product.rb +15 -0
- data/app/models/stall/models/curated_product_list.rb +22 -0
- data/app/models/stall/models/customer.rb +5 -8
- data/app/models/stall/models/image.rb +21 -0
- data/app/models/stall/models/manufacturer.rb +4 -0
- data/app/models/stall/models/product.rb +30 -7
- data/app/models/stall/models/product_category.rb +5 -2
- data/app/models/stall/models/product_list.rb +1 -1
- data/app/models/stall/models/product_suggestion.rb +14 -0
- data/app/models/stall/models/shipment.rb +0 -2
- data/app/models/stall/models/user.rb +18 -0
- data/app/models/stall/models/user_omniauth_account.rb +13 -0
- data/app/models/stall/models/variant.rb +11 -11
- data/app/models/user.rb +3 -0
- data/app/models/user_omniauth_account.rb +3 -0
- data/app/services/stall/add_to_cart_service.rb +19 -4
- data/app/services/stall/available_stocks_service.rb +11 -0
- data/app/services/stall/cart_credit_note_creation_service.rb +4 -0
- data/app/services/stall/cart_payment_validation_service.rb +5 -3
- data/app/services/stall/credit_usage_service.rb +8 -2
- data/app/services/stall/omniauth_user_authentication_service.rb +48 -0
- data/app/services/stall/product_list_staleness_handling_service.rb +6 -3
- data/app/services/stall/products_search_service.rb +23 -0
- data/app/services/stall/shipping_notification_service.rb +1 -1
- data/app/views/admin/carts/_filters.html.haml +10 -4
- data/app/views/admin/carts/_form.html.haml +9 -9
- data/app/views/admin/manufacturers/_form.html.haml +7 -0
- data/app/views/admin/manufacturers/_table.html.haml +8 -0
- data/app/views/admin/product_categories/_form.html.haml +7 -0
- data/app/views/admin/products/_form.html.haml +23 -0
- data/app/views/admin/products/_table.html.haml +4 -2
- data/app/views/checkout/steps/_informations.html.haml +2 -2
- data/app/views/para/admin/resources/_variant_row.html.haml +9 -1
- data/app/views/para/admin/resources/_variant_row_header.html.haml +14 -0
- data/app/views/para/stall/inputs/_variant_select.html.haml +3 -3
- data/app/views/para/stall/inputs/_variants_matrix.html.haml +7 -16
- data/app/views/para/stall/inputs/shipping_notes/new.html.haml +22 -0
- data/app/views/para/stall/inputs/shipping_notes/sent.html.haml +11 -0
- data/app/views/stall/carts/_cart.html.haml +1 -1
- data/app/views/stall/credit_note_adjustments/_form.html.haml +1 -1
- data/app/views/stall/curated_product_lists/show.html.haml +8 -0
- data/app/views/stall/customers/_fields.html.haml +17 -5
- data/app/views/stall/customers/_sign_in.html.haml +22 -10
- data/app/views/stall/line_items/_form.html.haml +2 -3
- data/app/views/stall/manufacturers/show.html.haml +8 -0
- data/app/views/stall/product_categories/show.html.haml +8 -0
- data/app/views/stall/products/_filters.html.haml +4 -0
- data/app/views/stall/products/_list.html.haml +7 -0
- data/app/views/stall/products/_product.html.haml +4 -0
- data/app/views/stall/products/_product_details.html.haml +13 -0
- data/app/views/stall/products/filters/_category_filter.html.haml +2 -0
- data/app/views/stall/products/filters/_manufacturer_filter.html.haml +2 -0
- data/app/views/stall/products/filters/_price_filter.html.haml +2 -0
- data/app/views/stall/products/filters/_property_filter.html.haml +2 -0
- data/app/views/stall/products/index.html.haml +8 -0
- data/app/views/stall/products/show.html.haml +26 -0
- data/config/locales/stall.fr.yml +97 -11
- data/db/migrate/20170221094450_add_slug_to_stall_manufacturers.rb +5 -0
- data/db/migrate/20170303122616_create_stall_product_suggestions.rb +13 -0
- data/db/migrate/20170303151939_add_position_to_stall_manufacturers.rb +5 -0
- data/db/migrate/20170308162740_create_stall_curated_product_lists.rb +10 -0
- data/db/migrate/20170308163532_create_stall_curated_list_products.rb +14 -0
- data/db/migrate/20170317103740_create_stall_users.rb +28 -0
- data/db/migrate/20170317104332_create_stall_user_omniauth_accounts.rb +14 -0
- data/db/migrate/20170320133513_fix_curated_product_list_bad_foreign_key.rb +6 -0
- data/db/migrate/20170321104203_create_stall_images.rb +11 -0
- data/db/migrate/20170321112248_remove_image_attachment_to_stall_products.rb +5 -0
- data/db/migrate/20170411134756_add_stock_to_stall_variants.rb +5 -0
- data/lib/ext/ransack.rb +13 -0
- data/lib/generators/stall/install/templates/initializer.rb +50 -15
- data/lib/generators/stall/service/service_generator.rb +0 -4
- data/lib/generators/stall/view/view_generator.rb +10 -8
- data/lib/para/stall/inputs/variant_select_input.rb +11 -1
- data/lib/para/stall/inputs/variants_matrix_input.rb +12 -6
- data/lib/stall.rb +14 -0
- data/lib/stall/addressable.rb +2 -2
- data/lib/stall/addresses/copy_source_to_target.rb +7 -3
- data/lib/stall/addresses/prefill_target_from_source.rb +4 -2
- data/lib/stall/cart_helper.rb +3 -3
- data/lib/stall/carts_cleaner.rb +2 -2
- data/lib/stall/checkout/informations_checkout_step.rb +2 -2
- data/lib/stall/config.rb +29 -9
- data/lib/stall/engine.rb +28 -13
- data/lib/stall/omniauth_provider.rb +41 -0
- data/lib/stall/payable.rb +3 -1
- data/lib/stall/product_filters.rb +12 -0
- data/lib/stall/product_filters/base_filter.rb +43 -0
- data/lib/stall/product_filters/builder.rb +59 -0
- data/lib/stall/product_filters/category_filter.rb +28 -0
- data/lib/stall/product_filters/manufacturer_filter.rb +19 -0
- data/lib/stall/product_filters/price_filter.rb +39 -0
- data/lib/stall/product_filters/property_filter.rb +38 -0
- data/lib/stall/routes.rb +40 -0
- data/lib/stall/shipping/calculator.rb +3 -1
- data/lib/stall/version.rb +1 -1
- metadata +158 -7
- data/app/assets/stylesheets/stall/carts.css +0 -4
data/lib/stall/config.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Stall
|
2
2
|
class Config
|
3
3
|
extend Stall::Utils::ConfigDSL
|
4
|
+
|
4
5
|
# Store name used in e-mails and other interfaces duisplaying such an
|
5
6
|
# information
|
6
7
|
param :store_name
|
@@ -20,17 +21,26 @@ module Stall
|
|
20
21
|
# Default prices precision for rounding
|
21
22
|
param :prices_precision, 2
|
22
23
|
|
24
|
+
# User omniauth providers
|
25
|
+
param :devise_for_user_config, { controllers: { omniauth_callbacks: 'stall/omniauth_callbacks' } }
|
26
|
+
|
23
27
|
# Engine's ApplicationController parent
|
24
28
|
param :application_controller_ancestor, '::ApplicationController'
|
25
29
|
|
26
30
|
param :mailers_parent_class, 'ActionMailer::Base'
|
27
31
|
|
28
|
-
# Default layout used for
|
32
|
+
# Default layout used for controllers
|
29
33
|
param :default_layout
|
30
34
|
|
35
|
+
# Default layout used for the checkout
|
36
|
+
param :checkout_layout
|
37
|
+
|
31
38
|
# Default currency for money objects
|
32
39
|
param :default_currency, 'EUR'
|
33
40
|
|
41
|
+
# Do not manage stocks on hand by default
|
42
|
+
param :manage_inventory, false
|
43
|
+
|
34
44
|
# Default app domain for building routes
|
35
45
|
param :default_app_domain
|
36
46
|
|
@@ -51,9 +61,6 @@ module Stall
|
|
51
61
|
# Duration after which an aborted cart is cleaned out by the rake task
|
52
62
|
param :aborted_carts_expires_after, 14.days
|
53
63
|
|
54
|
-
param :default_user_model_name, 'User'
|
55
|
-
param :default_user_helper_method, :current_user
|
56
|
-
|
57
64
|
# Configure the terms of service page path
|
58
65
|
param :terms_path, 'about:blank'
|
59
66
|
|
@@ -80,13 +87,15 @@ module Stall
|
|
80
87
|
end
|
81
88
|
|
82
89
|
# Fetch user config and add top-namespace lookup to avoid collision
|
83
|
-
# with Stall module services
|
90
|
+
# with Stall module services.
|
84
91
|
#
|
85
92
|
# Default allows looking up Stall namespace automatically, when no
|
86
93
|
# config has been given
|
87
94
|
def service_for(identifier)
|
88
95
|
class_name = if (service_name = services[identifier])
|
89
96
|
"::#{ services[identifier].gsub(/^::/, '') }"
|
97
|
+
elsif File.exists?(Rails.root.join('app', 'services', "#{ identifier }_service.rb"))
|
98
|
+
"::#{ identifier.to_s.camelize }Service"
|
90
99
|
else
|
91
100
|
"Stall::#{ identifier.to_s.camelize }Service"
|
92
101
|
end
|
@@ -98,15 +107,26 @@ module Stall
|
|
98
107
|
self.services.merge!(value)
|
99
108
|
end
|
100
109
|
|
101
|
-
def default_user_model
|
102
|
-
default_user_model_name.try(:constantize)
|
103
|
-
end
|
104
|
-
|
105
110
|
def default_currency_as_money
|
106
111
|
raw_default_currency && Money::Currency.new(raw_default_currency)
|
107
112
|
end
|
108
113
|
|
109
114
|
alias_method :raw_default_currency, :default_currency
|
110
115
|
alias_method :default_currency, :default_currency_as_money
|
116
|
+
|
117
|
+
# User omniauth providers
|
118
|
+
def omniauth_providers_configs
|
119
|
+
@omniauth_providers_configs ||= {}
|
120
|
+
end
|
121
|
+
|
122
|
+
def omniauth_provider(name, config = {})
|
123
|
+
omniauth_providers_configs[name] = config
|
124
|
+
end
|
125
|
+
|
126
|
+
def omniauth_providers
|
127
|
+
omniauth_providers_configs.map do |provider, config|
|
128
|
+
Stall::OmniauthProvider.new(provider, config.deep_dup)
|
129
|
+
end
|
130
|
+
end
|
111
131
|
end
|
112
132
|
end
|
data/lib/stall/engine.rb
CHANGED
@@ -24,29 +24,34 @@ module Stall
|
|
24
24
|
end
|
25
25
|
|
26
26
|
initializer 'stall.ensure_shipping_method_for_all_calculators' do
|
27
|
-
Stall::Shipping.calculators
|
28
|
-
ShippingMethod.where(identifier: name).first_or_create do |method|
|
29
|
-
method.name = name.to_s.humanize
|
30
|
-
end
|
31
|
-
end
|
27
|
+
register_class_models_for(ShippingMethod, Stall::Shipping.calculators)
|
32
28
|
end
|
33
29
|
|
34
|
-
initializer 'stall.
|
30
|
+
initializer 'stall.ensure_payment_method_for_all_gateways' do
|
35
31
|
require 'stall/payments/manual_payment_gateway'
|
36
|
-
end
|
37
32
|
|
38
|
-
|
39
|
-
Stall::Payments.gateways.each_key do |name|
|
40
|
-
PaymentMethod.where(identifier: name).first_or_create do |method|
|
41
|
-
method.name = name.to_s.humanize
|
42
|
-
end
|
43
|
-
end
|
33
|
+
register_class_models_for(PaymentMethod, Stall::Payments.gateways)
|
44
34
|
end
|
45
35
|
|
46
36
|
initializer 'stall.add_stall_plugin_to_para_config' do
|
47
37
|
Para.config.plugins += [:stall]
|
48
38
|
end
|
49
39
|
|
40
|
+
# For each omniauth provider in the config, declare a devise Omniauth
|
41
|
+
# provider
|
42
|
+
#
|
43
|
+
initializer 'stall.add_omniauth_providers_to_devise', before: 'devise.omniauth' do
|
44
|
+
Stall.config.omniauth_providers.each do |provider|
|
45
|
+
Devise.omniauth(provider.name, provider.app_id, provider.secret_key, provider.config)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Add ransack search predicates
|
50
|
+
#
|
51
|
+
initializer 'stall.add_omniauth_providers_to_devise', before: 'devise.omniauth' do
|
52
|
+
Stall::Ransack.configure
|
53
|
+
end
|
54
|
+
|
50
55
|
# Development : Configure rails generators to only generate the target
|
51
56
|
# files and not try to generate useless complementary files
|
52
57
|
#
|
@@ -57,5 +62,15 @@ module Stall
|
|
57
62
|
generators.javascripts false
|
58
63
|
generators.test_framework false
|
59
64
|
end
|
65
|
+
|
66
|
+
def register_class_models_for(model, classes)
|
67
|
+
return unless model.table_exists?
|
68
|
+
|
69
|
+
classes.each_key do |name|
|
70
|
+
model.where(identifier: name).first_or_create do |method|
|
71
|
+
method.name = name.to_s.humanize
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
60
75
|
end
|
61
76
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# This class is used as a config wrapper for devise's omniauth providers,
|
2
|
+
# allowing to easily configure new and existing providers.
|
3
|
+
#
|
4
|
+
module Stall
|
5
|
+
class OmniauthProvider
|
6
|
+
attr_reader :name, :config
|
7
|
+
|
8
|
+
def initialize(name, config = nil)
|
9
|
+
@name = name.to_s
|
10
|
+
|
11
|
+
config ||= {}
|
12
|
+
|
13
|
+
@icon = config.delete(:icon)
|
14
|
+
@display_name = config.delete(:display_name)
|
15
|
+
@app_id = config.delete(:app_id)
|
16
|
+
@secret_key = config.delete(:secret_key)
|
17
|
+
|
18
|
+
@config = config
|
19
|
+
end
|
20
|
+
|
21
|
+
def icon
|
22
|
+
@icon ||= name
|
23
|
+
end
|
24
|
+
|
25
|
+
def display_name
|
26
|
+
@display_name ||= name.humanize
|
27
|
+
end
|
28
|
+
|
29
|
+
def app_id
|
30
|
+
@app_id ||= ENV["#{ constant_name }_APP_ID"]
|
31
|
+
end
|
32
|
+
|
33
|
+
def secret_key
|
34
|
+
@secret_key ||= ENV["#{ constant_name }_SECRET_KEY"]
|
35
|
+
end
|
36
|
+
|
37
|
+
def constant_name
|
38
|
+
@constant_name ||= name.to_s.upcase
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/stall/payable.rb
CHANGED
@@ -17,7 +17,9 @@ module Stall
|
|
17
17
|
scope :aborted, ->(options = {}) {
|
18
18
|
joins('LEFT JOIN stall_payments ON stall_payments.cart_id = stall_product_lists.id')
|
19
19
|
.where(stall_payments: { paid_at: nil })
|
20
|
-
.older_than(
|
20
|
+
.older_than(
|
21
|
+
options.fetch(:before, Stall.config.aborted_carts_expires_after.ago)
|
22
|
+
)
|
21
23
|
}
|
22
24
|
|
23
25
|
delegate :paid?, to: :payment, allow_nil: true
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Stall
|
2
|
+
module ProductFilters
|
3
|
+
class BaseFilter
|
4
|
+
attr_reader :products, :options
|
5
|
+
|
6
|
+
def initialize(products, options = {})
|
7
|
+
@products = products
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def name
|
12
|
+
key.gsub(/_filter/, '')
|
13
|
+
end
|
14
|
+
|
15
|
+
def label
|
16
|
+
I18n.t("stall.products.filters.#{ key }")
|
17
|
+
end
|
18
|
+
|
19
|
+
# Can be overriden to hide the filter depending on certain conditions,
|
20
|
+
# e.g. there's more than one option so the filter is useful
|
21
|
+
#
|
22
|
+
def available?
|
23
|
+
options[:force] || true
|
24
|
+
end
|
25
|
+
|
26
|
+
def rendering_options(options = {})
|
27
|
+
{ partial: partial_path, locals: partial_locals }.deep_merge(options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def partial_path
|
31
|
+
"stall/products/filters/#{ key }"
|
32
|
+
end
|
33
|
+
|
34
|
+
def partial_locals
|
35
|
+
{ filter: self }
|
36
|
+
end
|
37
|
+
|
38
|
+
def key
|
39
|
+
@key ||= self.class.name.demodulize.underscore
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Stall
|
2
|
+
module ProductFilters
|
3
|
+
class Builder
|
4
|
+
attr_reader :products, :options
|
5
|
+
|
6
|
+
def initialize(products, options = {})
|
7
|
+
@products = products
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def filters
|
12
|
+
[category_filter, manufacturer_filter, price_filter] + properties_filters
|
13
|
+
end
|
14
|
+
|
15
|
+
def category_filter
|
16
|
+
CategoryFilter.new(products, options_for(:category)) if enabled?(:category)
|
17
|
+
end
|
18
|
+
|
19
|
+
def manufacturer_filter
|
20
|
+
ManufacturerFilter.new(products, options_for(:manufacturer)) if enabled?(:manufacturer)
|
21
|
+
end
|
22
|
+
|
23
|
+
def price_filter
|
24
|
+
PriceFilter.new(products, options_for(:price)) if enabled?(:price)
|
25
|
+
end
|
26
|
+
|
27
|
+
def properties_filters
|
28
|
+
if enabled?(:property)
|
29
|
+
properties.map do |property|
|
30
|
+
property_options = options_for(:property, property: property)
|
31
|
+
PropertyFilter.new(products, property_options)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
[]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def properties
|
41
|
+
Property.joins(
|
42
|
+
property_values: [
|
43
|
+
variant_property_values: [:variant]
|
44
|
+
]
|
45
|
+
)
|
46
|
+
.includes(:property_values)
|
47
|
+
.distinct
|
48
|
+
end
|
49
|
+
|
50
|
+
def options_for(filter_name, overrides = {})
|
51
|
+
(options[filter_name] || {}).deep_dup.merge(overrides)
|
52
|
+
end
|
53
|
+
|
54
|
+
def enabled?(filter_name)
|
55
|
+
options[filter_name] != false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Stall
|
2
|
+
module ProductFilters
|
3
|
+
class CategoryFilter < BaseFilter
|
4
|
+
def available?
|
5
|
+
options[:force] || collection.count > 1
|
6
|
+
end
|
7
|
+
|
8
|
+
def collection
|
9
|
+
@collection ||= ProductCategory.joins(:products)
|
10
|
+
.where(stall_products: { id: products.select(:id) })
|
11
|
+
.distinct
|
12
|
+
end
|
13
|
+
|
14
|
+
def param
|
15
|
+
:"#{ param_with_parents }_in"
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def param_with_parents
|
21
|
+
ProductCategory.max_depth.times.map do |index|
|
22
|
+
parents_string = index.times.map { 'parent' }.join('_').presence
|
23
|
+
['product_category', parents_string, 'id'].compact.join('_')
|
24
|
+
end.join('_or_')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Stall
|
2
|
+
module ProductFilters
|
3
|
+
class ManufacturerFilter < BaseFilter
|
4
|
+
def available?
|
5
|
+
options[:force] || collection.count > 1
|
6
|
+
end
|
7
|
+
|
8
|
+
def collection
|
9
|
+
@collection ||= Manufacturer.ordered.joins(:products)
|
10
|
+
.where(stall_products: { id: products.select(:id) })
|
11
|
+
.distinct
|
12
|
+
end
|
13
|
+
|
14
|
+
def param
|
15
|
+
:manufacturer_id_in
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Stall
|
2
|
+
module ProductFilters
|
3
|
+
class PriceFilter < BaseFilter
|
4
|
+
def available?
|
5
|
+
options[:force] || min != max
|
6
|
+
end
|
7
|
+
|
8
|
+
def min
|
9
|
+
return 0 unless variants.any?
|
10
|
+
variants.order(price_cents: :asc).first.price.to_d.floor
|
11
|
+
end
|
12
|
+
|
13
|
+
def max
|
14
|
+
return 0 unless variants.any?
|
15
|
+
variants.order(price_cents: :desc).first.price.to_d.ceil
|
16
|
+
end
|
17
|
+
|
18
|
+
def param
|
19
|
+
:variants_price_cents_between_cents
|
20
|
+
end
|
21
|
+
|
22
|
+
def ticks
|
23
|
+
min_tick = (min / 10.0).floor
|
24
|
+
max_tick = (max / 10.0).ceil
|
25
|
+
ticks_count = 4
|
26
|
+
|
27
|
+
(ticks_count + 1).times.map do |index|
|
28
|
+
((((max_tick - min_tick) / ticks_count.to_f) * index) + min_tick).to_i * 10
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def variants
|
35
|
+
@variants ||= Variant.where(product: products)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Stall
|
2
|
+
module ProductFilters
|
3
|
+
class PropertyFilter < BaseFilter
|
4
|
+
attr :property
|
5
|
+
|
6
|
+
def initialize(*)
|
7
|
+
super
|
8
|
+
@property = options[:property]
|
9
|
+
end
|
10
|
+
|
11
|
+
def available?
|
12
|
+
@available ||= (options[:force] || collection.count > 1)
|
13
|
+
end
|
14
|
+
|
15
|
+
def name
|
16
|
+
property.name.parameterize
|
17
|
+
end
|
18
|
+
|
19
|
+
def label
|
20
|
+
property.name
|
21
|
+
end
|
22
|
+
|
23
|
+
def param
|
24
|
+
:variants_property_values_id_in
|
25
|
+
end
|
26
|
+
|
27
|
+
def collection
|
28
|
+
@collection ||= property.property_values.joins(variants: :product)
|
29
|
+
.where(stall_products: { id: products.select(:id) })
|
30
|
+
.distinct
|
31
|
+
end
|
32
|
+
|
33
|
+
def partial_locals
|
34
|
+
{ filter: self, property: property }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|