spree_sale_prices 1.0.0 → 2.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- metadata +4 -50
- data/.gitignore +0 -14
- data/.rspec +0 -1
- data/Gemfile +0 -5
- data/LICENSE +0 -26
- data/README.md +0 -158
- data/Rakefile +0 -21
- data/Versionfile +0 -10
- data/app/assets/javascripts/spree/backend/spree_sale_prices.js +0 -0
- data/app/assets/javascripts/spree/frontend/spree_sale_prices.js +0 -0
- data/app/assets/stylesheets/spree/backend/spree_sale_prices.css +0 -0
- data/app/assets/stylesheets/spree/frontend/spree_sale_prices.css +0 -0
- data/app/controllers/spree/admin/sale_prices_controller.rb +0 -43
- data/app/helpers/spree/base_helper_decorator.rb +0 -30
- data/app/models/spree/calculator/dollar_amount_sale_price_calculator.rb +0 -14
- data/app/models/spree/calculator/fixed_amount_sale_price_calculator.rb +0 -12
- data/app/models/spree/calculator/percent_off_sale_price_calculator.rb +0 -12
- data/app/models/spree/price_decorator.rb +0 -97
- data/app/models/spree/product_decorator.rb +0 -50
- data/app/models/spree/sale_price.rb +0 -63
- data/app/models/spree/variant_decorator.rb +0 -71
- data/app/overrides/admin_product_tabs.rb +0 -6
- data/app/views/spree/admin/sale_prices/_sale_price.html.slim +0 -8
- data/app/views/spree/admin/sale_prices/_table.html.slim +0 -18
- data/app/views/spree/admin/sale_prices/create.js.erb +0 -1
- data/app/views/spree/admin/sale_prices/destroy.js.erb +0 -1
- data/app/views/spree/admin/sale_prices/index.html.slim +0 -36
- data/config/locales/de.yml +0 -14
- data/config/locales/en.yml +0 -14
- data/config/routes.rb +0 -7
- data/db/migrate/20120403135246_create_sale_prices.rb +0 -19
- data/db/migrate/20140309000000_change_data_type_for_value.rb +0 -5
- data/lib/generators/spree_sale_prices/install/install_generator.rb +0 -19
- data/lib/spree_sale_prices.rb +0 -2
- data/lib/spree_sale_prices/engine.rb +0 -20
- data/lib/spree_sale_prices/factories.rb +0 -35
- data/spec/models/price_spec.rb +0 -58
- data/spec/models/product_spec.rb +0 -18
- data/spec/models/sale_price_spec.rb +0 -38
- data/spec/models/variant_spec.rb +0 -150
- data/spec/spec_helper.rb +0 -87
- data/spree_sale_prices.gemspec +0 -28
@@ -1,12 +0,0 @@
|
|
1
|
-
module Spree
|
2
|
-
class Calculator::PercentOffSalePriceCalculator < Spree::Calculator
|
3
|
-
# TODO validate that the sale price is between 0 and 1
|
4
|
-
def self.description
|
5
|
-
"Calculates the sale price for a Variant by taking off a percentage of the original price"
|
6
|
-
end
|
7
|
-
|
8
|
-
def compute(sale_price)
|
9
|
-
(1.0 - sale_price.value.to_f) * sale_price.variant.original_price.to_f
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
@@ -1,97 +0,0 @@
|
|
1
|
-
Spree::Price.class_eval do
|
2
|
-
has_many :sale_prices
|
3
|
-
|
4
|
-
def put_on_sale(value, params = {})
|
5
|
-
new_sale(value, params).save
|
6
|
-
end
|
7
|
-
|
8
|
-
def new_sale(value, params = {})
|
9
|
-
sale_price_params = {
|
10
|
-
value: value,
|
11
|
-
start_at: params.fetch(:start_at, Time.now),
|
12
|
-
end_at: params.fetch(:end_at, nil),
|
13
|
-
enabled: params.fetch(:enabled, true),
|
14
|
-
calculator: params.fetch(:calculator_type, Spree::Calculator::FixedAmountSalePriceCalculator.new)
|
15
|
-
}
|
16
|
-
return sale_prices.new(sale_price_params)
|
17
|
-
end
|
18
|
-
|
19
|
-
# TODO make update_sale method
|
20
|
-
|
21
|
-
def active_sale
|
22
|
-
first_sale(sale_prices.active) if on_sale?
|
23
|
-
end
|
24
|
-
alias :current_sale :active_sale
|
25
|
-
|
26
|
-
def next_active_sale
|
27
|
-
first_sale(sale_prices) if sale_prices.present?
|
28
|
-
end
|
29
|
-
alias :next_current_sale :next_active_sale
|
30
|
-
|
31
|
-
def sale_price
|
32
|
-
active_sale.calculated_price if on_sale?
|
33
|
-
end
|
34
|
-
|
35
|
-
def sale_price=(value)
|
36
|
-
if on_sale?
|
37
|
-
active_sale.update_attribute(:value, value)
|
38
|
-
else
|
39
|
-
put_on_sale(value)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def discount_percent
|
44
|
-
return 0.0 unless original_price > 0
|
45
|
-
return 0.0 unless on_sale?
|
46
|
-
(1 - (sale_price / original_price)) * 100
|
47
|
-
end
|
48
|
-
|
49
|
-
def on_sale?
|
50
|
-
sale_prices.active.present? && first_sale(sale_prices.active).value < original_price
|
51
|
-
end
|
52
|
-
|
53
|
-
def original_price
|
54
|
-
self[:amount]
|
55
|
-
end
|
56
|
-
|
57
|
-
def original_price=(value)
|
58
|
-
self[:amount] = Spree::LocalizedNumber.parse(value)
|
59
|
-
end
|
60
|
-
|
61
|
-
def price
|
62
|
-
on_sale? ? sale_price : original_price
|
63
|
-
end
|
64
|
-
|
65
|
-
def price=(price)
|
66
|
-
if on_sale?
|
67
|
-
sale_price = price
|
68
|
-
else
|
69
|
-
self[:amount] = Spree::LocalizedNumber.parse(price)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def amount
|
74
|
-
price
|
75
|
-
end
|
76
|
-
|
77
|
-
def enable_sale
|
78
|
-
next_active_sale.enable if next_active_sale.present?
|
79
|
-
end
|
80
|
-
|
81
|
-
def disable_sale
|
82
|
-
active_sale.disable if active_sale.present?
|
83
|
-
end
|
84
|
-
|
85
|
-
def start_sale(end_time = nil)
|
86
|
-
next_active_sale.start(end_time) if next_active_sale.present?
|
87
|
-
end
|
88
|
-
|
89
|
-
def stop_sale
|
90
|
-
active_sale.stop if active_sale.present?
|
91
|
-
end
|
92
|
-
|
93
|
-
private
|
94
|
-
def first_sale(scope)
|
95
|
-
scope.order("created_at DESC").first
|
96
|
-
end
|
97
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
Spree::Product.class_eval do
|
2
|
-
|
3
|
-
has_many :sale_prices, through: :prices
|
4
|
-
|
5
|
-
# Essentially all read values here are delegated to reading the value on the Master variant
|
6
|
-
# All write values will write to all variants (including the Master) unless that method's all_variants parameter is
|
7
|
-
# set to false, in which case it will only write to the Master variant.
|
8
|
-
|
9
|
-
delegate_belongs_to :master, :active_sale_in, :current_sale_in, :next_active_sale_in, :next_current_sale_in,
|
10
|
-
:sale_price_in, :on_sale_in?, :original_price_in, :discount_percent_in, :discount_percent, :sale_price,
|
11
|
-
:original_price, :on_sale?
|
12
|
-
|
13
|
-
# TODO also accept a class reference for calculator type instead of only a string
|
14
|
-
def put_on_sale(value, params = {})
|
15
|
-
all_variants = params[:all_variants] || true
|
16
|
-
run_on_variants(all_variants) { |v| v.put_on_sale(value, params) }
|
17
|
-
self.touch
|
18
|
-
end
|
19
|
-
|
20
|
-
alias :create_sale :put_on_sale
|
21
|
-
|
22
|
-
def enable_sale(all_variants = true)
|
23
|
-
run_on_variants(all_variants) { |v| v.enable_sale }
|
24
|
-
self.touch
|
25
|
-
end
|
26
|
-
|
27
|
-
def disable_sale(all_variants = true)
|
28
|
-
run_on_variants(all_variants) { |v| v.disable_sale }
|
29
|
-
self.touch
|
30
|
-
end
|
31
|
-
|
32
|
-
def start_sale(end_time = nil, all_variants = true)
|
33
|
-
run_on_variants(all_variants) { |v| v.start_sale(end_time) }
|
34
|
-
self.touch
|
35
|
-
end
|
36
|
-
|
37
|
-
def stop_sale(all_variants = true)
|
38
|
-
run_on_variants(all_variants) { |v| v.stop_sale }
|
39
|
-
self.touch
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
def run_on_variants(all_variants, &block)
|
44
|
-
if all_variants && variants.present?
|
45
|
-
variants.each { |v| block.call v }
|
46
|
-
end
|
47
|
-
block.call master
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
module Spree
|
2
|
-
class SalePrice < ActiveRecord::Base
|
3
|
-
|
4
|
-
belongs_to :price, class_name: "Spree::Price"
|
5
|
-
delegate_belongs_to :price, :currency
|
6
|
-
|
7
|
-
has_one :variant, through: :price
|
8
|
-
|
9
|
-
has_one :calculator, class_name: "Spree::Calculator", as: :calculable, dependent: :destroy
|
10
|
-
validates :calculator, presence: true
|
11
|
-
accepts_nested_attributes_for :calculator
|
12
|
-
|
13
|
-
scope :active, -> { where(enabled: true).where('(start_at <= ? OR start_at IS NULL) AND (end_at >= ? OR end_at IS NULL)', Time.now, Time.now) }
|
14
|
-
|
15
|
-
before_destroy :touch_product
|
16
|
-
# TODO make this work or remove it
|
17
|
-
#def self.calculators
|
18
|
-
# Rails.application.config.spree.calculators.send(self.to_s.tableize.gsub('/', '_').sub('spree_', ''))
|
19
|
-
#end
|
20
|
-
|
21
|
-
def calculator_type
|
22
|
-
calculator.class.to_s if calculator
|
23
|
-
end
|
24
|
-
|
25
|
-
def calculated_price
|
26
|
-
calculator.compute self
|
27
|
-
end
|
28
|
-
|
29
|
-
def enable
|
30
|
-
update_attribute(:enabled, true)
|
31
|
-
end
|
32
|
-
|
33
|
-
def disable
|
34
|
-
update_attribute(:enabled, false)
|
35
|
-
end
|
36
|
-
|
37
|
-
def active?
|
38
|
-
Spree::SalePrice.active.include? self
|
39
|
-
end
|
40
|
-
|
41
|
-
def start(end_time = nil)
|
42
|
-
end_time = nil if end_time.present? && end_time <= Time.now # if end_time is not in the future then make it nil (no end)
|
43
|
-
attr = { end_at: end_time, enabled: true }
|
44
|
-
attr[:start_at] = Time.now if self.start_at.present? && self.start_at > Time.now # only set start_at if it's not set in the past
|
45
|
-
update_attributes(attr)
|
46
|
-
end
|
47
|
-
|
48
|
-
def stop
|
49
|
-
update_attributes({ end_at: Time.now, enabled: false })
|
50
|
-
end
|
51
|
-
|
52
|
-
# Convenience method for displaying the price of a given sale_price in the table
|
53
|
-
def display_price
|
54
|
-
Spree::Money.new(value || 0, { currency: price.currency })
|
55
|
-
end
|
56
|
-
|
57
|
-
protected
|
58
|
-
def touch_product
|
59
|
-
self.variant.product.touch
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
Spree::Variant.class_eval do
|
2
|
-
|
3
|
-
has_many :sale_prices, through: :prices
|
4
|
-
|
5
|
-
delegate_belongs_to :default_price, :sale_price, :original_price, :on_sale?, :discount_percent
|
6
|
-
|
7
|
-
def put_on_sale(value, params = {})
|
8
|
-
currencies = params.fetch(:currencies, [])
|
9
|
-
if params[:currency].present?
|
10
|
-
currencies << params[:currency] unless currencies.include? params[:currency]
|
11
|
-
end
|
12
|
-
run_on_prices(currencies) { |p| p.put_on_sale value, params }
|
13
|
-
end
|
14
|
-
alias :create_sale :put_on_sale
|
15
|
-
|
16
|
-
# TODO make update_sale method
|
17
|
-
|
18
|
-
def active_sale_in(currency)
|
19
|
-
price_in(currency).active_sale
|
20
|
-
end
|
21
|
-
alias :current_sale_in :active_sale_in
|
22
|
-
|
23
|
-
def next_active_sale_in(currency)
|
24
|
-
price_in(currency).next_active_sale
|
25
|
-
end
|
26
|
-
alias :next_current_sale_in :next_active_sale_in
|
27
|
-
|
28
|
-
def sale_price_in(currency)
|
29
|
-
Spree::Price.new variant_id: self.id, currency: currency, amount: price_in(currency).sale_price
|
30
|
-
end
|
31
|
-
|
32
|
-
def discount_percent_in(currency)
|
33
|
-
price_in(currency).discount_percent
|
34
|
-
end
|
35
|
-
|
36
|
-
def on_sale_in?(currency)
|
37
|
-
price_in(currency).on_sale?
|
38
|
-
end
|
39
|
-
|
40
|
-
def original_price_in(currency)
|
41
|
-
Spree::Price.new variant_id: self.id, currency: currency, amount: price_in(currency).original_price
|
42
|
-
end
|
43
|
-
|
44
|
-
def enable_sale(currencies = nil)
|
45
|
-
run_on_prices(currencies) { |p| p.enable_sale }
|
46
|
-
end
|
47
|
-
|
48
|
-
def disable_sale(currencies = nil)
|
49
|
-
run_on_prices(currencies) { |p| p.disable_sale }
|
50
|
-
end
|
51
|
-
|
52
|
-
def start_sale(end_time = nil, currencies = nil)
|
53
|
-
run_on_prices(currencies) { |p| p.start_sale end_time }
|
54
|
-
end
|
55
|
-
|
56
|
-
def stop_sale(currencies = nil)
|
57
|
-
run_on_prices(currencies) { |p| p.stop_sale }
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
# runs on all prices or on the ones with the currencies you've specified
|
62
|
-
def run_on_prices(currencies = nil, &block)
|
63
|
-
if currencies.present? && currencies.any?
|
64
|
-
prices_with_currencies = prices.select { |p| currencies.include?(p.currency) }
|
65
|
-
prices_with_currencies.each { |p| block.call p }
|
66
|
-
else
|
67
|
-
prices.each { |p| block.call p }
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
@@ -1,6 +0,0 @@
|
|
1
|
-
Deface::Override.new(virtual_path: "spree/admin/shared/_product_tabs",
|
2
|
-
name: "add_sale_prices_tab",
|
3
|
-
insert_bottom: "[data-hook='admin_product_tabs']",
|
4
|
-
text: "<%= content_tag :li, :class => ('active' if current == 'Product Sale Prices') do %><%= link_to_with_icon 'money', Spree.t(:product_sale_prices), admin_product_sale_prices_path(@product) %><% end %>",
|
5
|
-
disabled: false)
|
6
|
-
|
@@ -1,8 +0,0 @@
|
|
1
|
-
tr data-hook="products_row" id = spree_dom_id(sale_price) class = "spree-product-sale-price"
|
2
|
-
td.align-center = sale_price.active? ? 'Yes' : ''
|
3
|
-
td = sale_price.display_price.to_html
|
4
|
-
td = (l sale_price.start_at ) if sale_price.start_at
|
5
|
-
td = (l sale_price.end_at) if sale_price.end_at
|
6
|
-
td.align-center = sale_price.enabled
|
7
|
-
td.actions
|
8
|
-
= link_to_delete sale_price, {url: admin_product_sale_price_url(product, sale_price.id), no_text: true}
|
@@ -1,18 +0,0 @@
|
|
1
|
-
table.index#product_sale_prices data-hook="sale_price_table"
|
2
|
-
colgroup
|
3
|
-
col
|
4
|
-
col
|
5
|
-
col style="width: 30%"
|
6
|
-
col style="width: 30%"
|
7
|
-
col
|
8
|
-
col
|
9
|
-
thead
|
10
|
-
tr data-hook="products_header"
|
11
|
-
th = Spree.t('sale_price_active')
|
12
|
-
th = Spree.t('sale_price')
|
13
|
-
th = Spree.t('sale_price_start_at')
|
14
|
-
th = Spree.t('sale_price_end_at')
|
15
|
-
th = Spree.t('sale_price_enabled')
|
16
|
-
th.actions
|
17
|
-
tbody
|
18
|
-
= render partial: "sale_price", collection: product.master.sale_prices, locals: {product: product}
|
@@ -1 +0,0 @@
|
|
1
|
-
$('table#product_sale_prices').replaceWith('<%= j render partial: "table", locals: {product: @product} %>');
|
@@ -1 +0,0 @@
|
|
1
|
-
$('td.spree-product-sale-price#<%= j spree_dom_id(@sale_price) %>').remove();
|
@@ -1,36 +0,0 @@
|
|
1
|
-
= render :partial => 'spree/admin/shared/product_sub_menu'
|
2
|
-
= render :partial => 'spree/admin/shared/product_tabs', :locals => {:current => "Product Sale Prices"}
|
3
|
-
|
4
|
-
= csrf_meta_tag
|
5
|
-
|
6
|
-
#add-line-item
|
7
|
-
fieldset
|
8
|
-
legend align="center" = Spree.t('add_product_sale_prices')
|
9
|
-
|
10
|
-
= form_for [:admin, @product, Spree::SalePrice.new], remote: true do |f|
|
11
|
-
.row
|
12
|
-
.columns.three
|
13
|
-
= label_tag t('original_price')
|
14
|
-
= text_field_tag '', @product.original_price.to_f, disabled: true
|
15
|
-
|
16
|
-
.row
|
17
|
-
.columns.three
|
18
|
-
= f.label :value, t('sale_price_amount')
|
19
|
-
= f.text_field :value
|
20
|
-
.columns.three
|
21
|
-
= f.label :currency, t('sale_price_currency')
|
22
|
-
= f.select :currency, options_for_select(supported_currencies_for_sale_price)
|
23
|
-
|
24
|
-
.row
|
25
|
-
.columns.three
|
26
|
-
= f.label :start_at, t('sale_price_start_at')
|
27
|
-
= f.text_field :start_at, class: "datepicker"
|
28
|
-
.columns.three
|
29
|
-
= f.label :end_at, t('sale_price_end_at')
|
30
|
-
= f.text_field :end_at, class: "datepicker"
|
31
|
-
.columns.three
|
32
|
-
= f.label :submit, style: 'visibility: hidden;'
|
33
|
-
= f.submit "Add Sale Price"
|
34
|
-
|
35
|
-
#product-sale-prices-table
|
36
|
-
= render partial: "table", locals: { product: @product }
|
data/config/locales/de.yml
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# Sample localization file for English. Add more files in this directory for other locales.
|
2
|
-
# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
|
3
|
-
|
4
|
-
de:
|
5
|
-
sale_price: "Aktionspreis"
|
6
|
-
original_price: "Originalpreis (Standard Währung)"
|
7
|
-
product_sale_prices: "Aktionspreise des Produktes"
|
8
|
-
add_product_sale_prices: "Aktionspreise hinzufügen"
|
9
|
-
sale_price_amount: 'Wert'
|
10
|
-
sale_price_active: 'Aktiv'
|
11
|
-
sale_price_currency: "Währung"
|
12
|
-
sale_price_start_at: "Startdatum"
|
13
|
-
sale_price_end_at: "Enddatum"
|
14
|
-
sale_price_enabled: "Aktiviert"
|
data/config/locales/en.yml
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# Sample localization file for English. Add more files in this directory for other locales.
|
2
|
-
# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
|
3
|
-
|
4
|
-
en:
|
5
|
-
sale_price: "Sale Price"
|
6
|
-
original_price: "Original Price (Standard Currency)"
|
7
|
-
product_sale_prices: "Product Sale Prices"
|
8
|
-
add_product_sale_prices: "Add Product Sale Price"
|
9
|
-
sale_price_amount: 'Amount'
|
10
|
-
sale_price_active: 'Active'
|
11
|
-
sale_price_currency: "Currency"
|
12
|
-
sale_price_start_at: "Sale Start Date"
|
13
|
-
sale_price_end_at: "Sale End Date"
|
14
|
-
sale_price_enabled: "Enabled"
|
data/config/routes.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
class CreateSalePrices < ActiveRecord::Migration
|
2
|
-
def change
|
3
|
-
create_table :spree_sale_prices do |t|
|
4
|
-
t.integer :price_id
|
5
|
-
t.float :value
|
6
|
-
t.datetime :start_at
|
7
|
-
t.datetime :end_at
|
8
|
-
t.boolean :enabled
|
9
|
-
t.timestamps
|
10
|
-
end
|
11
|
-
|
12
|
-
# Getting active sale prices for a price
|
13
|
-
add_index :spree_sale_prices, [:price_id, :start_at, :end_at, :enabled], name: "index_active_sale_prices_for_price"
|
14
|
-
# Getting all active sale prices for all prices
|
15
|
-
add_index :spree_sale_prices, [:start_at, :end_at, :enabled], name: "index_active_sale_prices_for_all_variants"
|
16
|
-
# Getting all sale prices for a price
|
17
|
-
add_index :spree_sale_prices, :price_id, name: "index_sale_prices_for_price"
|
18
|
-
end
|
19
|
-
end
|