solidus_volume_pricing 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.hound.yml +40 -0
- data/.rspec +3 -0
- data/.rubocop.yml +8 -0
- data/.travis.yml +14 -0
- data/CONTRIBUTING.md +81 -0
- data/Gemfile +13 -0
- data/Guardfile +9 -0
- data/LICENSE.md +26 -0
- data/README.md +112 -0
- data/Rakefile +21 -0
- data/app/assets/javascripts/spree/backend/solidus_volume_pricing.js +16 -0
- data/app/controllers/spree/admin/variants_controller_decorator.rb +32 -0
- data/app/controllers/spree/admin/volume_price_models_controller.rb +27 -0
- data/app/controllers/spree/admin/volume_prices_controller.rb +11 -0
- data/app/helpers/spree/base_helper_decorator.rb +19 -0
- data/app/models/spree/line_item_decorator.rb +27 -0
- data/app/models/spree/user_decorator.rb +10 -0
- data/app/models/spree/variant_decorator.rb +104 -0
- data/app/models/spree/volume_price.rb +35 -0
- data/app/models/spree/volume_price_model.rb +8 -0
- data/app/overrides/spree/admin/shared/sub_menu/_configuration/add_volume_price_model_admin_menu_links.html.erb.deface +3 -0
- data/app/overrides/views_decorator.rb +13 -0
- data/app/views/spree/admin/shared/_vp_product_tab.html.erb +3 -0
- data/app/views/spree/admin/variants/_edit_fields.html.erb +33 -0
- data/app/views/spree/admin/variants/volume_prices.html.erb +39 -0
- data/app/views/spree/admin/volume_price_models/_form.html.erb +9 -0
- data/app/views/spree/admin/volume_price_models/_list.html.erb +23 -0
- data/app/views/spree/admin/volume_price_models/edit.html.erb +12 -0
- data/app/views/spree/admin/volume_price_models/index.html.erb +18 -0
- data/app/views/spree/admin/volume_price_models/new.html.erb +12 -0
- data/app/views/spree/admin/volume_prices/_edit_fields.html.erb +31 -0
- data/app/views/spree/admin/volume_prices/_volume_price_fields.html.erb +33 -0
- data/app/views/spree/products/_volume_pricing.html.erb +15 -0
- data/bin/rails +7 -0
- data/config/locales/de.yml +18 -0
- data/config/locales/en.yml +18 -0
- data/config/locales/pt.yml +18 -0
- data/config/locales/ru.yml +18 -0
- data/config/locales/sv.yml +18 -0
- data/config/locales/tr.yml +18 -0
- data/config/routes.rb +12 -0
- data/db/migrate/20081119145604_create_volume_prices.rb +16 -0
- data/db/migrate/20110203174010_change_display_name_for_volume_prices.rb +9 -0
- data/db/migrate/20111206173307_prefix_volume_pricing_table_names.rb +5 -0
- data/db/migrate/20121115043422_add_discount_type_column.rb +5 -0
- data/db/migrate/20150513200904_add_role_to_volume_price.rb +5 -0
- data/db/migrate/20150603143015_create_spree_volume_price_models.rb +18 -0
- data/lib/generators/solidus_volume_pricing/install/install_generator.rb +24 -0
- data/lib/solidus_volume_pricing.rb +6 -0
- data/lib/solidus_volume_pricing/engine.rb +42 -0
- data/lib/solidus_volume_pricing/version.rb +18 -0
- data/solidus_volume_pricing.gemspec +40 -0
- data/spec/controllers/spree/admin/variants_controller_spec.rb +27 -0
- data/spec/factories/volume_price_factory.rb +12 -0
- data/spec/helpers/base_helper_spec.rb +22 -0
- data/spec/models/spree/line_item_spec.rb +34 -0
- data/spec/models/spree/order_spec.rb +49 -0
- data/spec/models/spree/variant_spec.rb +306 -0
- data/spec/models/spree/volume_price_spec.rb +121 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/support/capybara.rb +12 -0
- data/spec/support/database_cleaner.rb +24 -0
- data/spec/support/factory_girl.rb +7 -0
- data/spec/support/spree.rb +10 -0
- metadata +337 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
Spree::BaseHelper.class_eval do
|
2
|
+
def display_volume_price(variant, quantity = 1, user = nil)
|
3
|
+
Spree::Money.new(
|
4
|
+
variant.volume_price(quantity, user),
|
5
|
+
currency: Spree::Config[:currency]
|
6
|
+
).to_html
|
7
|
+
end
|
8
|
+
|
9
|
+
def display_volume_price_earning_percent(variant, quantity = 1, user = nil)
|
10
|
+
variant.volume_price_earning_percent(quantity, user).round.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def display_volume_price_earning_amount(variant, quantity = 1, user = nil)
|
14
|
+
Spree::Money.new(
|
15
|
+
variant.volume_price_earning_amount(quantity, user),
|
16
|
+
currency: Spree::Config[:currency]
|
17
|
+
).to_html
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Spree::LineItem.class_eval do
|
2
|
+
# pattern grabbed from: http://stackoverflow.com/questions/4470108/
|
3
|
+
|
4
|
+
# the idea here is compatibility with spree_sale_products
|
5
|
+
# trying to create a 'calculation stack' wherein the best valid price is
|
6
|
+
# chosen for the product. This is mainly for compatibility with spree_sale_products
|
7
|
+
#
|
8
|
+
# Assumption here is that the volume price currency is the same as the product currency
|
9
|
+
old_copy_price = instance_method(:copy_price)
|
10
|
+
define_method(:copy_price) do
|
11
|
+
old_copy_price.bind(self).call
|
12
|
+
return unless variant
|
13
|
+
|
14
|
+
if variant
|
15
|
+
if changed? && changes.keys.include?('quantity')
|
16
|
+
vprice = variant.volume_price(quantity, order.user)
|
17
|
+
if price.present? && vprice <= variant.price
|
18
|
+
self.price = vprice and return
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
self.price = variant.price if price.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
self.price = variant.price if price.nil?
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
Spree::Variant.class_eval do
|
2
|
+
has_and_belongs_to_many :volume_price_models
|
3
|
+
has_many :volume_prices, -> { order(position: :asc) }, dependent: :destroy
|
4
|
+
has_many :model_volume_prices, -> { order(position: :asc) }, class_name: 'Spree::VolumePrice', through: :volume_price_models, source: :volume_prices
|
5
|
+
accepts_nested_attributes_for :volume_prices, allow_destroy: true,
|
6
|
+
reject_if: proc { |volume_price|
|
7
|
+
volume_price[:amount].blank? && volume_price[:range].blank?
|
8
|
+
}
|
9
|
+
|
10
|
+
def join_volume_prices(user = nil)
|
11
|
+
table = Spree::VolumePrice.arel_table
|
12
|
+
|
13
|
+
if user
|
14
|
+
Spree::VolumePrice.where(
|
15
|
+
(table[:variant_id].eq(id)
|
16
|
+
.or(table[:volume_price_model_id].in(volume_price_models.ids)))
|
17
|
+
.and(table[:role_id].eq(user.resolve_role))
|
18
|
+
)
|
19
|
+
.order(position: :asc)
|
20
|
+
else
|
21
|
+
Spree::VolumePrice.where(
|
22
|
+
(table[:variant_id]
|
23
|
+
.eq(id)
|
24
|
+
.or(table[:volume_price_model_id].in(volume_price_models.ids)))
|
25
|
+
.and(table[:role_id].eq(nil))
|
26
|
+
).order(position: :asc)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# calculates the price based on quantity
|
31
|
+
def volume_price(quantity, user = nil)
|
32
|
+
compute_volume_price_quantities :volume_price, price, quantity, user
|
33
|
+
end
|
34
|
+
|
35
|
+
# return percent of earning
|
36
|
+
def volume_price_earning_percent(quantity, user = nil)
|
37
|
+
compute_volume_price_quantities :volume_price_earning_percent, 0, quantity, user
|
38
|
+
end
|
39
|
+
|
40
|
+
# return amount of earning
|
41
|
+
def volume_price_earning_amount(quantity, user = nil)
|
42
|
+
compute_volume_price_quantities :volume_price_earning_amount, 0, quantity, user
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def use_master_variant_volume_pricing?
|
48
|
+
Spree::Config.use_master_variant_volume_pricing && !(product.master.join_volume_prices.count == 0)
|
49
|
+
end
|
50
|
+
|
51
|
+
def compute_volume_price_quantities(type, default_price, quantity, user)
|
52
|
+
volume_prices = join_volume_prices user
|
53
|
+
if volume_prices.count == 0
|
54
|
+
if use_master_variant_volume_pricing?
|
55
|
+
product.master.send(type, quantity, user)
|
56
|
+
else
|
57
|
+
return default_price
|
58
|
+
end
|
59
|
+
else
|
60
|
+
volume_prices.each do |volume_price|
|
61
|
+
if volume_price.include?(quantity)
|
62
|
+
return send "compute_#{type}".to_sym, volume_price
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# No price ranges matched.
|
67
|
+
default_price
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def compute_volume_price(volume_price)
|
72
|
+
case volume_price.discount_type
|
73
|
+
when 'price'
|
74
|
+
return volume_price.amount
|
75
|
+
when 'dollar'
|
76
|
+
return price - volume_price.amount
|
77
|
+
when 'percent'
|
78
|
+
return price * (1 - volume_price.amount)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def compute_volume_price_earning_percent(volume_price)
|
83
|
+
case volume_price.discount_type
|
84
|
+
when 'price'
|
85
|
+
diff = price - volume_price.amount
|
86
|
+
return (diff * 100 / price).round
|
87
|
+
when 'dollar'
|
88
|
+
return (volume_price.amount * 100 / price).round
|
89
|
+
when 'percent'
|
90
|
+
return (volume_price.amount * 100).round
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def compute_volume_price_earning_amount(volume_price)
|
95
|
+
case volume_price.discount_type
|
96
|
+
when 'price'
|
97
|
+
return price - volume_price.amount
|
98
|
+
when 'dollar'
|
99
|
+
return volume_price.amount
|
100
|
+
when 'percent'
|
101
|
+
return price - (price * (1 - volume_price.amount))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Spree::VolumePrice < ActiveRecord::Base
|
2
|
+
belongs_to :variant, touch: true
|
3
|
+
belongs_to :volume_price_model, touch: true
|
4
|
+
belongs_to :spree_role, class_name: 'Spree::Role', foreign_key: 'role_id'
|
5
|
+
acts_as_list scope: [:variant_id, :volume_price_model_id]
|
6
|
+
|
7
|
+
validates :amount, presence: true
|
8
|
+
validates :discount_type,
|
9
|
+
presence: true,
|
10
|
+
inclusion: {
|
11
|
+
in: %w(price dollar percent),
|
12
|
+
message: I18n.t(:'activerecord.errors.messages.is_not_a_valid_volume_price_type', value: self)
|
13
|
+
}
|
14
|
+
validates :range,
|
15
|
+
format: {
|
16
|
+
with: /\(?[0-9]+(?:\.{2,3}[0-9]+|\+\)?)/,
|
17
|
+
message: I18n.t(:'activerecord.errors.messages.must_be_in_format')
|
18
|
+
}
|
19
|
+
|
20
|
+
OPEN_ENDED = /\(?[0-9]+\+\)?/
|
21
|
+
|
22
|
+
def include?(quantity)
|
23
|
+
if open_ended?
|
24
|
+
bound = /\d+/.match(range)[0].to_i
|
25
|
+
return quantity >= bound
|
26
|
+
else
|
27
|
+
range.to_range === quantity
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# indicates whether or not the range is a true Ruby range or an open ended range with no upper bound
|
32
|
+
def open_ended?
|
33
|
+
OPEN_ENDED =~ range
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class Spree::VolumePriceModel < ActiveRecord::Base
|
2
|
+
has_many :variants
|
3
|
+
has_many :volume_prices, -> { order(position: :asc) }, dependent: :destroy
|
4
|
+
accepts_nested_attributes_for :volume_prices, allow_destroy: true,
|
5
|
+
reject_if: proc { |volume_price|
|
6
|
+
volume_price[:amount].blank? && volume_price[:range].blank?
|
7
|
+
}
|
8
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Deface::Override.new(
|
2
|
+
virtual_path: 'spree/admin/shared/_product_tabs',
|
3
|
+
name: 'add_volume_pricing_admin_tab',
|
4
|
+
insert_bottom: '[data-hook="admin_product_tabs"]',
|
5
|
+
partial: 'spree/admin/shared/vp_product_tab'
|
6
|
+
)
|
7
|
+
|
8
|
+
Deface::Override.new(
|
9
|
+
virtual_path: 'spree/admin/variants/edit',
|
10
|
+
name: 'add_volume_pricing_field_to_variant',
|
11
|
+
insert_after: '[data-hook="admin_variant_edit_form"]',
|
12
|
+
partial: 'spree/admin/variants/edit_fields'
|
13
|
+
)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<% content_for :page_actions do %>
|
2
|
+
<span id="new_add_volume_price" data-hook>
|
3
|
+
<%= button_link_to Spree.t(:add_volume_price), 'javascript:;', {
|
4
|
+
icon: 'add', :'data-target' => 'tbody#volume_prices', class: 'btn-success spree_add_fields', id: 'add_volume_price' } %>
|
5
|
+
</span>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<h3><%= Spree.t(:volume_prices) %></h3>
|
9
|
+
<table class="table">
|
10
|
+
<thead>
|
11
|
+
<tr>
|
12
|
+
<th><%= Spree.t(:name) %></th>
|
13
|
+
<th><%= Spree.t(:discount_type) %></th>
|
14
|
+
<th><%= Spree.t(:range) %></th>
|
15
|
+
<th><%= Spree.t(:amount) %></th>
|
16
|
+
<th><%= Spree.t(:position) %></th>
|
17
|
+
<th><%= Spree.t(:role) %></th>
|
18
|
+
<th><%= Spree.t(:action) %></th>
|
19
|
+
</tr>
|
20
|
+
</thead>
|
21
|
+
<tbody id="volume_prices">
|
22
|
+
<%= f.fields_for :volume_prices do |vp_form| %>
|
23
|
+
<%= render partial: 'spree/admin/volume_prices/volume_price_fields', locals: { f: vp_form } %>
|
24
|
+
<% end %>
|
25
|
+
</tbody>
|
26
|
+
<tbody id="volume_price_models">
|
27
|
+
<%= f.field_container :volume_price_model, class: ['form-group'] do %>
|
28
|
+
<%= f.label :volume_price_model_id, Spree.t(:volume_price_model) %>
|
29
|
+
<%= f.collection_select(:volume_price_model_ids, Spree::VolumePriceModel.all, :id, :name, { include_blank: Spree.t('match_choices.none') }, { class: 'select2', disabled: (cannot? :edit, Spree::VolumePriceModel) }) %>
|
30
|
+
<%= f.error_message_on :volume_price_model %>
|
31
|
+
<% end %>
|
32
|
+
</tbody>
|
33
|
+
</table>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<%= render 'spree/admin/shared/product_tabs', current: Spree.t(:volume_pricing) %>
|
2
|
+
<%= render 'spree/shared/error_messages', target: @variant %>
|
3
|
+
|
4
|
+
<% content_for :page_actions do %>
|
5
|
+
<span id="new_add_volume_price" data-hook>
|
6
|
+
<%= button_link_to Spree.t(:add_volume_price), 'javascript:;', {
|
7
|
+
icon: 'add', :'data-target' => 'tbody#volume_prices', class: 'btn-success spree_add_fields', id: 'add_volume_price'} %>
|
8
|
+
</span>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%= form_for(@variant, url: admin_product_variant_path(@product, @variant), html: { method: :put }) do |f| %>
|
12
|
+
<h3><%= Spree.t(:volume_prices) %></h3>
|
13
|
+
<table class="table">
|
14
|
+
<thead>
|
15
|
+
<tr>
|
16
|
+
<th><%= Spree.t(:name) %></th>
|
17
|
+
<th><%= Spree.t(:discount_type) %></th>
|
18
|
+
<th><%= Spree.t(:range) %></th>
|
19
|
+
<th><%= Spree.t(:amount) %></th>
|
20
|
+
<th><%= Spree.t(:position) %></th>
|
21
|
+
<th><%= Spree.t(:role) %></th>
|
22
|
+
<th class="actions"></th>
|
23
|
+
</tr>
|
24
|
+
</thead>
|
25
|
+
<tbody id="volume_prices">
|
26
|
+
<%= f.fields_for :volume_prices do |vp_form| %>
|
27
|
+
<%= render partial: 'spree/admin/volume_prices/volume_price_fields', locals: { f: vp_form } %>
|
28
|
+
<% end %>
|
29
|
+
</tbody>
|
30
|
+
<tbody id="volume_price_models">
|
31
|
+
<%= f.field_container :volume_price_model, class: ['form-group'] do %>
|
32
|
+
<%= f.label :volume_price_model_id, Spree.t(:volume_price_model) %>
|
33
|
+
<%= f.collection_select(:volume_price_model_ids, Spree::VolumePriceModel.all, :id, :name, { include_blank: Spree.t('match_choices.none') }, { class: 'select2', disabled: (cannot? :edit, Spree::VolumePriceModel) }) %>
|
34
|
+
<%= f.error_message_on :volume_price_model %>
|
35
|
+
<% end %>
|
36
|
+
</tbody>
|
37
|
+
</table>
|
38
|
+
<%= render 'spree/admin/shared/edit_resource_links' %>
|
39
|
+
<% end %>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<div data-hook="admin_inside_volume_price_model_form" class="form-group">
|
2
|
+
<%= f.field_container :name, class: ['form-group'] do %>
|
3
|
+
<%= f.label :name, Spree.t(:name) %> <span class="required">*</span>
|
4
|
+
<%= error_message_on :volume_price_model, :name, :class => 'error-message' %>
|
5
|
+
<%= text_field :volume_price_model, :name, :class => 'form-control' %>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<%= render 'spree/admin/volume_prices/edit_fields', f: f %>
|
9
|
+
</div>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<table class="table sortable" id='listing_volume_price_models' data-hook data-sortable-link="<%#= update_positions_admin_volume_price_models_url %>">
|
2
|
+
<thead>
|
3
|
+
<tr data-hook="volume_price_models_header">
|
4
|
+
<th class="no-border"></th>
|
5
|
+
<th><%= Spree.t(:name) %></th>
|
6
|
+
<th class="actions"></th>
|
7
|
+
</tr>
|
8
|
+
</thead>
|
9
|
+
<tbody>
|
10
|
+
<% @volume_price_models.each do |price_model| %>
|
11
|
+
<tr id="<%= spree_dom_id price_model %>" data-hook="volume_price_models_row">
|
12
|
+
<td class="move-handle">
|
13
|
+
<span class="icon icon-sort handle"></span>
|
14
|
+
</td>
|
15
|
+
<td><%= price_model.name %></td>
|
16
|
+
<td class="actions actions-2 text-right">
|
17
|
+
<%= link_to_edit price_model.id, no_text: true %>
|
18
|
+
<%= link_to_delete price_model, no_text: true %>
|
19
|
+
</td>
|
20
|
+
</tr>
|
21
|
+
<% end %>
|
22
|
+
</tbody>
|
23
|
+
</table>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= Spree.t(:volume_price_model_edit) %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<%= form_for [:admin, @volume_price_model] do |f| %>
|
6
|
+
<fieldset>
|
7
|
+
<%= render partial: 'form', locals: { f: f } %>
|
8
|
+
</fieldset>
|
9
|
+
|
10
|
+
<%= render 'spree/admin/shared/edit_resource_links' %>
|
11
|
+
|
12
|
+
<% end %>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= "Volume Price Models" %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for :page_actions do %>
|
6
|
+
<%= button_link_to Spree.t(:new_volume_price_model), new_object_url, class: "btn-success", icon: 'add', id: 'admin_new_volume_price_model_link' %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<% if @volume_price_models.any? %>
|
10
|
+
<div id="list-volume-price-models" data-hook>
|
11
|
+
<%= render 'list' %>
|
12
|
+
</div>
|
13
|
+
<% else %>
|
14
|
+
<div class="alert alert-info no-objects-found">
|
15
|
+
<%= Spree.t(:no_resource_found, resource: "Volume Price Models") %>,
|
16
|
+
<%= link_to Spree.t(:add_one), new_object_url %>!
|
17
|
+
</div>
|
18
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= Spree.t(:new_volume_price_model) %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<%= form_for [:admin, @volume_price_model] do |f| %>
|
6
|
+
<fieldset>
|
7
|
+
<%= render partial: 'form', locals: { f: f } %>
|
8
|
+
<div class="form-actions" data-hook="buttons">
|
9
|
+
<%= button Spree.t(:create), 'save' %>
|
10
|
+
</div>
|
11
|
+
</fieldset>
|
12
|
+
<% end %>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<% content_for :page_actions do %>
|
2
|
+
<span id="new_add_volume_price" data-hook>
|
3
|
+
<%= button_link_to Spree.t(:add_volume_price), 'javascript:;', {
|
4
|
+
icon: 'add',
|
5
|
+
:'data-target' => 'tbody#volume_prices',
|
6
|
+
class: 'btn-success spree_add_fields',
|
7
|
+
id: 'add_volume_price'
|
8
|
+
} %>
|
9
|
+
</span>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<h3><%= Spree.t(:volume_prices) %></h3>
|
13
|
+
<table class="table">
|
14
|
+
<thead>
|
15
|
+
<tr>
|
16
|
+
<th><%= Spree.t(:name) %></th>
|
17
|
+
<th><%= Spree.t(:discount_type) %></th>
|
18
|
+
<th><%= Spree.t(:range) %></th>
|
19
|
+
<th><%= Spree.t(:amount) %></th>
|
20
|
+
<th><%= Spree.t(:position) %></th>
|
21
|
+
<th><%= Spree.t(:role) %></th>
|
22
|
+
<th><%= Spree.t(:action) %></th>
|
23
|
+
</tr>
|
24
|
+
</thead>
|
25
|
+
<tbody id="volume_prices">
|
26
|
+
<%= f.fields_for :volume_prices do |vp_form| %>
|
27
|
+
<%= render partial: 'spree/admin/volume_prices/volume_price_fields', locals: { f: vp_form } %>
|
28
|
+
<% end %>
|
29
|
+
</tbody>
|
30
|
+
</table>
|
31
|
+
<br/><br/>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<tr class="volume_price fields">
|
2
|
+
<td>
|
3
|
+
<%= error_message_on(f.object, :name) %>
|
4
|
+
<%= f.text_field :name, size: 10, class: 'form-control' %>
|
5
|
+
</td>
|
6
|
+
<td>
|
7
|
+
<%= error_message_on(f.object, :discount_type) %>
|
8
|
+
<%= f.select :discount_type, [
|
9
|
+
["#{Spree.t(:total_price)}", 'price'],
|
10
|
+
["#{Spree.t(:percent_discount)}", 'percent'],
|
11
|
+
["#{Spree.t(:price_discount)}", 'dollar']
|
12
|
+
], { inlcude_blank: true }, class: 'select2' %>
|
13
|
+
</td>
|
14
|
+
<td>
|
15
|
+
<%= error_message_on(f.object, :range) %>
|
16
|
+
<%= f.text_field :range, size: 10, class: 'form-control' %>
|
17
|
+
</td>
|
18
|
+
<td>
|
19
|
+
<%= error_message_on(f.object, :amount) %>
|
20
|
+
<%= f.text_field :amount, size: 10, class: 'form-control' %>
|
21
|
+
</td>
|
22
|
+
<td>
|
23
|
+
<%= error_message_on(f.object, :position) %>
|
24
|
+
<%= f.text_field :position, size: 3, class: 'form-control' %>
|
25
|
+
</td>
|
26
|
+
<td>
|
27
|
+
<%= error_message_on(f.object, :role_id) %>
|
28
|
+
<%= f.collection_select(:role_id, Spree::Role.all, :id, :name, { include_blank: Spree.t('match_choices.none') }, { class: 'select2' }) %>
|
29
|
+
</td>
|
30
|
+
<td class="actions">
|
31
|
+
<%= link_to_icon_remove_fields f %>
|
32
|
+
</td>
|
33
|
+
</tr>
|