spree_promo 1.2.5 → 1.3.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/app/assets/javascripts/admin/promotions.js +10 -1
- data/app/assets/stylesheets/admin/spree_promo.css +0 -1
- data/app/controllers/spree/admin/promotion_actions_controller.rb +2 -2
- data/app/controllers/spree/admin/promotion_rules_controller.rb +2 -2
- data/app/controllers/spree/checkout_controller_decorator.rb +5 -16
- data/app/controllers/spree/orders_controller_decorator.rb +2 -18
- data/app/controllers/spree/store_controller_decorator.rb +55 -0
- data/app/models/spree/order_decorator.rb +5 -14
- data/app/models/spree/order_updater_decorator.rb +14 -0
- data/app/models/spree/promotion/actions/create_adjustment.rb +12 -22
- data/app/models/spree/promotion/actions/create_line_items.rb +2 -18
- data/app/models/spree/promotion/rules/first_order.rb +2 -19
- data/app/models/spree/promotion/rules/user_logged_in.rb +8 -1
- data/app/models/spree/promotion.rb +6 -6
- data/app/models/spree/promotion_action_line_item.rb +2 -0
- data/app/overrides/promo_admin_tabs.rb +1 -1
- data/app/views/spree/admin/promotion_actions/create.js.erb +6 -3
- data/app/views/spree/admin/promotion_actions/destroy.js.erb +1 -2
- data/app/views/spree/admin/promotion_rules/create.js.erb +6 -0
- data/app/views/spree/admin/promotion_rules/destroy.js.erb +1 -1
- data/app/views/spree/admin/promotions/_actions.html.erb +21 -15
- data/app/views/spree/admin/promotions/_form.html.erb +55 -51
- data/app/views/spree/admin/promotions/_promotion_action.html.erb +5 -5
- data/app/views/spree/admin/promotions/_promotion_rule.html.erb +5 -4
- data/app/views/spree/admin/promotions/_rules.html.erb +39 -26
- data/app/views/spree/admin/promotions/actions/_create_adjustment.html.erb +8 -9
- data/app/views/spree/admin/promotions/actions/_create_line_items.html.erb +19 -40
- data/app/views/spree/admin/promotions/edit.html.erb +22 -6
- data/app/views/spree/admin/promotions/index.html.erb +49 -35
- data/app/views/spree/admin/promotions/new.html.erb +13 -3
- data/app/views/spree/admin/promotions/rules/_item_total.html.erb +6 -7
- data/app/views/spree/admin/promotions/rules/_landing_page.html.erb +5 -8
- data/app/views/spree/admin/promotions/rules/_product.html.erb +7 -8
- data/app/views/spree/admin/promotions/rules/_user_logged_in.html.erb +0 -3
- data/config/locales/en.yml +8 -2
- data/config/routes.rb +1 -1
- data/db/migrate/20120831092359_spree_promo_one_two.rb +45 -0
- data/lib/spree/promo/engine.rb +5 -6
- metadata +11 -26
- data/app/assets/stylesheets/admin/promotions.css +0 -44
- data/db/migrate/20100419190933_rename_coupons_to_promotions.rb +0 -10
- data/db/migrate/20100426100726_create_promotion_rules.rb +0 -24
- data/db/migrate/20100501084722_match_policy_for_promotions.rb +0 -5
- data/db/migrate/20100501095202_create_promotion_rules_users.rb +0 -14
- data/db/migrate/20100502163939_name_for_promotions.rb +0 -5
- data/db/migrate/20100923095305_update_calculable_type_for_promotions.rb +0 -9
- data/db/migrate/20101026184833_migrate_adjustments.rb +0 -9
- data/db/migrate/20110331094351_promotion_changes_to_subclass_of_activator.rb +0 -22
- data/db/migrate/20110404123358_create_promotion_actions.rb +0 -9
- data/db/migrate/20110601202923_create_promotion_action_line_items.rb +0 -10
- data/db/migrate/20120119024707_namespace_promo_tables.rb +0 -85
- data/db/migrate/20120119024708_create_spree_pending_promotions.rb +0 -11
- data/db/migrate/20120119024721_content_visited_event.rb +0 -29
@@ -1,6 +1,15 @@
|
|
1
1
|
var initProductActions = function(){
|
2
2
|
|
3
|
-
|
3
|
+
// Add classes on promotion items for design
|
4
|
+
$('a.delete').live('mouseover mouseout', function(event) {
|
5
|
+
if (event.type == 'mouseover') {
|
6
|
+
$(this).parent().addClass('action-remove');
|
7
|
+
} else {
|
8
|
+
$(this).parent().removeClass('action-remove');
|
9
|
+
}
|
10
|
+
});
|
11
|
+
|
12
|
+
$(".variant_autocomplete").variantAutocomplete();
|
4
13
|
|
5
14
|
$('.calculator-fields').each(function(){
|
6
15
|
var $fields_container = $(this);
|
@@ -5,7 +5,7 @@ class Spree::Admin::PromotionActionsController < Spree::Admin::BaseController
|
|
5
5
|
@promotion_action = params[:action_type].constantize.new(params[:promotion_action])
|
6
6
|
@promotion_action.promotion = @promotion
|
7
7
|
if @promotion_action.save
|
8
|
-
flash
|
8
|
+
flash[:success] = I18n.t(:successfully_created, :resource => I18n.t(:promotion_action))
|
9
9
|
end
|
10
10
|
respond_to do |format|
|
11
11
|
format.html { redirect_to spree.edit_admin_promotion_path(@promotion)}
|
@@ -17,7 +17,7 @@ class Spree::Admin::PromotionActionsController < Spree::Admin::BaseController
|
|
17
17
|
@promotion = Spree::Promotion.find(params[:promotion_id])
|
18
18
|
@promotion_action = @promotion.promotion_actions.find(params[:id])
|
19
19
|
if @promotion_action.destroy
|
20
|
-
flash
|
20
|
+
flash[:success] = I18n.t(:successfully_removed, :resource => I18n.t(:promotion_action))
|
21
21
|
end
|
22
22
|
respond_to do |format|
|
23
23
|
format.html { redirect_to spree.edit_admin_promotion_path(@promotion)}
|
@@ -10,7 +10,7 @@ class Spree::Admin::PromotionRulesController < Spree::Admin::BaseController
|
|
10
10
|
@promotion_rule = promotion_rule_type.constantize.new(params[:promotion_rule])
|
11
11
|
@promotion_rule.promotion = @promotion
|
12
12
|
if @promotion_rule.save
|
13
|
-
flash
|
13
|
+
flash[:success] = I18n.t(:successfully_created, :resource => I18n.t(:promotion_rule))
|
14
14
|
end
|
15
15
|
respond_to do |format|
|
16
16
|
format.html { redirect_to spree.edit_admin_promotion_path(@promotion)}
|
@@ -22,7 +22,7 @@ class Spree::Admin::PromotionRulesController < Spree::Admin::BaseController
|
|
22
22
|
@promotion = Spree::Promotion.find(params[:promotion_id])
|
23
23
|
@promotion_rule = @promotion.promotion_rules.find(params[:id])
|
24
24
|
if @promotion_rule.destroy
|
25
|
-
flash
|
25
|
+
flash[:success] = I18n.t(:successfully_removed, :resource => I18n.t(:promotion_rule))
|
26
26
|
end
|
27
27
|
respond_to do |format|
|
28
28
|
format.html { redirect_to spree.edit_admin_promotion_path(@promotion)}
|
@@ -5,36 +5,25 @@ Spree::CheckoutController.class_eval do
|
|
5
5
|
if @order.update_attributes(object_params)
|
6
6
|
|
7
7
|
fire_event('spree.checkout.update')
|
8
|
-
|
9
|
-
if @order.coupon_code.present?
|
10
|
-
event_name = "spree.checkout.coupon_code_added"
|
11
|
-
if promo = Spree::Promotion.with_coupon_code(@order.coupon_code).where(:event_name => event_name).first
|
12
|
-
fire_event(event_name, :coupon_code => @order.coupon_code)
|
13
|
-
# If it doesn't exist, raise an error!
|
14
|
-
# Giving them another chance to enter a valid coupon code
|
15
|
-
else
|
16
|
-
flash[:error] = t(:promotion_not_found)
|
17
|
-
render :edit and return
|
18
|
-
end
|
19
|
-
end
|
8
|
+
render :edit and return unless apply_coupon_code
|
20
9
|
|
21
10
|
if @order.next
|
22
11
|
state_callback(:after)
|
23
12
|
else
|
24
13
|
flash[:error] = t(:payment_processing_failed)
|
25
|
-
|
14
|
+
redirect_to checkout_state_path(@order.state)
|
26
15
|
return
|
27
16
|
end
|
28
17
|
|
29
18
|
if @order.state == 'complete' || @order.completed?
|
30
19
|
flash.notice = t(:order_processed_successfully)
|
31
20
|
flash[:commerce_tracking] = 'nothing special'
|
32
|
-
|
21
|
+
redirect_to completion_route
|
33
22
|
else
|
34
|
-
|
23
|
+
redirect_to checkout_state_path(@order.state)
|
35
24
|
end
|
36
25
|
else
|
37
|
-
|
26
|
+
render :edit
|
38
27
|
end
|
39
28
|
end
|
40
29
|
|
@@ -3,14 +3,8 @@ Spree::OrdersController.class_eval do
|
|
3
3
|
def update
|
4
4
|
@order = current_order
|
5
5
|
if @order.update_attributes(params[:order])
|
6
|
-
|
7
|
-
|
8
|
-
flash[:notice] = t(:coupon_code_applied)
|
9
|
-
else
|
10
|
-
flash[:error] = t(:promotion_not_found)
|
11
|
-
render :edit and return
|
12
|
-
end
|
13
|
-
end
|
6
|
+
render :edit and return unless apply_coupon_code
|
7
|
+
|
14
8
|
@order.line_items = @order.line_items.select {|li| li.quantity > 0 }
|
15
9
|
fire_event('spree.order.contents_changed')
|
16
10
|
respond_with(@order) do |format|
|
@@ -27,14 +21,4 @@ Spree::OrdersController.class_eval do
|
|
27
21
|
end
|
28
22
|
end
|
29
23
|
|
30
|
-
def apply_coupon_code
|
31
|
-
return if @order.coupon_code.blank?
|
32
|
-
if promo = Spree::Promotion.with_coupon_code(@order.coupon_code).first
|
33
|
-
if promo.order_activatable?(@order)
|
34
|
-
fire_event('spree.checkout.coupon_code_added', :coupon_code => @order.coupon_code)
|
35
|
-
true
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
24
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
Spree::StoreController.class_eval do
|
2
|
+
|
3
|
+
protected
|
4
|
+
def apply_coupon_code
|
5
|
+
if @order.coupon_code.present?
|
6
|
+
# check if coupon code is already applied
|
7
|
+
if @order.adjustments.promotion.eligible.detect { |p| p.originator.promotion.code == @order.coupon_code }.present?
|
8
|
+
flash[:notice] = t(:coupon_code_already_applied)
|
9
|
+
true
|
10
|
+
else
|
11
|
+
event_name = "spree.checkout.coupon_code_added"
|
12
|
+
|
13
|
+
# TODO should restrict to payload's event name?
|
14
|
+
promotion = Spree::Promotion.find_by_code(@order.coupon_code)
|
15
|
+
|
16
|
+
if promotion.present?
|
17
|
+
if promotion.expired?
|
18
|
+
flash[:error] = t(:coupon_code_expired)
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
if promotion.usage_limit_exceeded?
|
23
|
+
flash[:error] = t(:coupon_code_max_usage)
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
|
27
|
+
previous_promo = @order.adjustments.promotion.eligible.first
|
28
|
+
fire_event(event_name, :coupon_code => @order.coupon_code)
|
29
|
+
promo = @order.adjustments.promotion.detect { |p| p.originator.promotion.code == @order.coupon_code }
|
30
|
+
|
31
|
+
if promo.present? and promo.eligible
|
32
|
+
flash[:success] = t(:coupon_code_applied)
|
33
|
+
true
|
34
|
+
elsif previous_promo.present? and promo.present?
|
35
|
+
flash[:error] = t(:coupon_code_better_exists)
|
36
|
+
false
|
37
|
+
elsif promo.present?
|
38
|
+
flash[:error] = t(:coupon_code_not_eligible)
|
39
|
+
false
|
40
|
+
else
|
41
|
+
# if the promotion was created after the order
|
42
|
+
flash[:error] = t(:coupon_code_not_found)
|
43
|
+
false
|
44
|
+
end
|
45
|
+
else
|
46
|
+
flash[:error] = t(:coupon_code_not_found)
|
47
|
+
false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
else
|
51
|
+
true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
Spree::Order.class_eval do
|
2
2
|
attr_accessible :coupon_code
|
3
|
-
|
3
|
+
attr_reader :coupon_code
|
4
|
+
|
5
|
+
def coupon_code=(code)
|
6
|
+
@coupon_code = code.strip.downcase rescue nil
|
7
|
+
end
|
4
8
|
|
5
9
|
# Tells us if there if the specified promotion is already associated with the order
|
6
10
|
# regardless of whether or not its currently eligible. Useful because generally
|
@@ -9,19 +13,6 @@ Spree::Order.class_eval do
|
|
9
13
|
!! adjustments.promotion.reload.detect { |credit| credit.originator.promotion.id == promotion.id }
|
10
14
|
end
|
11
15
|
|
12
|
-
unless self.method_defined?('update_adjustments_with_promotion_limiting')
|
13
|
-
def update_adjustments_with_promotion_limiting
|
14
|
-
update_adjustments_without_promotion_limiting
|
15
|
-
return if adjustments.promotion.eligible.none?
|
16
|
-
most_valuable_adjustment = adjustments.promotion.eligible.max{|a,b| a.amount.abs <=> b.amount.abs}
|
17
|
-
current_adjustments = (adjustments.promotion.eligible - [most_valuable_adjustment])
|
18
|
-
current_adjustments.each do |adjustment|
|
19
|
-
adjustment.update_attribute_without_callbacks(:eligible, false)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
alias_method_chain :update_adjustments, :promotion_limiting
|
23
|
-
end
|
24
|
-
|
25
16
|
def promo_total
|
26
17
|
adjustments.eligible.promotion.map(&:amount).sum
|
27
18
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Spree::OrderUpdater.class_eval do
|
2
|
+
unless self.method_defined?('update_adjustments_with_promotion_limiting')
|
3
|
+
def update_adjustments_with_promotion_limiting
|
4
|
+
update_adjustments_without_promotion_limiting
|
5
|
+
return if adjustments.promotion.eligible.none?
|
6
|
+
most_valuable_adjustment = adjustments.promotion.eligible.max{|a,b| a.amount.abs <=> b.amount.abs}
|
7
|
+
current_adjustments = (adjustments.promotion.eligible - [most_valuable_adjustment])
|
8
|
+
current_adjustments.each do |adjustment|
|
9
|
+
adjustment.update_attribute_without_callbacks(:eligible, false)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
alias_method_chain :update_adjustments, :promotion_limiting
|
13
|
+
end
|
14
|
+
end
|
@@ -1,36 +1,27 @@
|
|
1
1
|
module Spree
|
2
2
|
class Promotion
|
3
3
|
module Actions
|
4
|
-
# Responsible for the creation and management of an adjustment since an
|
5
|
-
# an adjustment uses its originator to also update its eligiblity and amount
|
6
4
|
class CreateAdjustment < PromotionAction
|
7
5
|
calculated_adjustments
|
8
6
|
|
9
|
-
has_many :adjustments, :as => :originator, :dependent => :destroy
|
10
|
-
|
11
7
|
delegate :eligible?, :to => :promotion
|
12
8
|
|
13
9
|
before_validation :ensure_action_has_calculator
|
14
10
|
|
15
|
-
# Creates the adjustment related to a promotion for the order passed
|
16
|
-
# through options hash
|
17
11
|
def perform(options = {})
|
18
|
-
order = options[:order]
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
return unless order = options[:order]
|
13
|
+
# Nothing to do if the promotion is already associated with the order
|
14
|
+
return if order.promotion_credit_exists?(promotion)
|
15
|
+
|
16
|
+
order.adjustments.promotion.reload.clear
|
17
|
+
order.update!
|
18
|
+
create_adjustment("#{I18n.t(:promotion)} (#{promotion.name})", order, order)
|
19
|
+
order.update!
|
22
20
|
end
|
23
21
|
|
24
|
-
#
|
25
|
-
# adjustments are added all the time. They will get their
|
26
|
-
# set to false if the amount is 0
|
27
|
-
#
|
28
|
-
# Currently an adjustment is created even when its promotion is not eligible.
|
29
|
-
# This helps to figure out later which adjustments should be eligible
|
30
|
-
# as the order is being updated
|
31
|
-
#
|
32
|
-
# BTW The order is updated (through order#update) every time an adjustment
|
33
|
-
# is saved
|
22
|
+
# override of CalculatedAdjustments#create_adjustment so promotional
|
23
|
+
# adjustments are added all the time. They will get their eligability
|
24
|
+
# set to false if the amount is 0
|
34
25
|
def create_adjustment(label, target, calculable, mandatory=false)
|
35
26
|
amount = compute_amount(calculable)
|
36
27
|
params = { :amount => amount,
|
@@ -41,8 +32,7 @@ module Spree
|
|
41
32
|
target.adjustments.create(params, :without_protection => true)
|
42
33
|
end
|
43
34
|
|
44
|
-
# Ensure a negative amount which does not exceed the sum of the order's
|
45
|
-
# item_total and ship_total
|
35
|
+
# Ensure a negative amount which does not exceed the sum of the order's item_total and ship_total
|
46
36
|
def compute_amount(calculable)
|
47
37
|
[(calculable.item_total + calculable.ship_total), super.to_f.abs].min * -1
|
48
38
|
end
|
@@ -3,14 +3,12 @@ module Spree
|
|
3
3
|
module Actions
|
4
4
|
class CreateLineItems < PromotionAction
|
5
5
|
has_many :promotion_action_line_items, :foreign_key => :promotion_action_id
|
6
|
+
accepts_nested_attributes_for :promotion_action_line_items
|
7
|
+
attr_accessible :promotion_action_line_items_attributes
|
6
8
|
|
7
|
-
delegate :eligible?, :to => :promotion
|
8
|
-
|
9
|
-
attr_accessor :line_items_string
|
10
9
|
|
11
10
|
def perform(options = {})
|
12
11
|
return unless order = options[:order]
|
13
|
-
return unless eligible?(order)
|
14
12
|
promotion_action_line_items.each do |item|
|
15
13
|
current_quantity = order.quantity_of(item.variant)
|
16
14
|
if current_quantity < item.quantity
|
@@ -19,20 +17,6 @@ module Spree
|
|
19
17
|
end
|
20
18
|
end
|
21
19
|
end
|
22
|
-
|
23
|
-
def line_items_string
|
24
|
-
promotion_action_line_items.map { |li| "#{li.variant_id}x#{li.quantity}" }.join(',')
|
25
|
-
end
|
26
|
-
|
27
|
-
def line_items_string=(value)
|
28
|
-
promotion_action_line_items.destroy_all
|
29
|
-
value.to_s.split(',').each do |str|
|
30
|
-
variant_id, quantity = str.split('x')
|
31
|
-
if variant_id && quantity && variant = Variant.find_by_id(variant_id)
|
32
|
-
promotion_action_line_items.create({:variant => variant, :quantity => quantity.to_i}, :without_protection => true)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
20
|
end
|
37
21
|
end
|
38
22
|
end
|
@@ -2,27 +2,10 @@ module Spree
|
|
2
2
|
class Promotion
|
3
3
|
module Rules
|
4
4
|
class FirstOrder < PromotionRule
|
5
|
-
attr_reader :user, :email
|
6
|
-
|
7
5
|
def eligible?(order, options = {})
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
if user || email
|
12
|
-
completed_orders.blank? || (completed_orders.first == order)
|
13
|
-
else
|
14
|
-
false
|
15
|
-
end
|
6
|
+
user = order.try(:user) || options[:user]
|
7
|
+
!!(user && user.orders.complete.count == 0)
|
16
8
|
end
|
17
|
-
|
18
|
-
private
|
19
|
-
def completed_orders
|
20
|
-
user ? user.orders.complete : orders_by_email
|
21
|
-
end
|
22
|
-
|
23
|
-
def orders_by_email
|
24
|
-
Spree::Order.where(:email => email).complete
|
25
|
-
end
|
26
9
|
end
|
27
10
|
end
|
28
11
|
end
|
@@ -4,7 +4,14 @@ module Spree
|
|
4
4
|
class UserLoggedIn < PromotionRule
|
5
5
|
|
6
6
|
def eligible?(order, options = {})
|
7
|
-
|
7
|
+
# this is tricky. We couldn't use any of the devise methods since we aren't in the controller.
|
8
|
+
# we need to rely on the controller already having done this for us.
|
9
|
+
|
10
|
+
# The thinking is that the controller should have some sense of what state
|
11
|
+
# we should be in before firing events,
|
12
|
+
# so the controller will have to set this field.
|
13
|
+
|
14
|
+
return options && options[:user_signed_in]
|
8
15
|
end
|
9
16
|
|
10
17
|
end
|
@@ -36,16 +36,12 @@ module Spree
|
|
36
36
|
where(:advertise => true)
|
37
37
|
end
|
38
38
|
|
39
|
-
def self.with_coupon_code(coupon_code)
|
40
|
-
search(:code_cont => coupon_code).result
|
41
|
-
end
|
42
|
-
|
43
39
|
def activate(payload)
|
44
40
|
return unless order_activatable? payload[:order]
|
45
41
|
|
46
42
|
if code.present?
|
47
|
-
event_code = payload[:coupon_code]
|
48
|
-
return unless event_code == self.code
|
43
|
+
event_code = payload[:coupon_code]
|
44
|
+
return unless event_code == self.code
|
49
45
|
end
|
50
46
|
|
51
47
|
if path.present?
|
@@ -101,5 +97,9 @@ module Spree
|
|
101
97
|
credits.count
|
102
98
|
end
|
103
99
|
|
100
|
+
def code=(coupon_code)
|
101
|
+
write_attribute(:code, (coupon_code.downcase.strip rescue nil))
|
102
|
+
end
|
103
|
+
|
104
104
|
end
|
105
105
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Deface::Override.new(:virtual_path => "spree/layouts/admin",
|
2
2
|
:name => "promo_admin_tabs",
|
3
3
|
:insert_bottom => "[data-hook='admin_tabs'], #admin_tabs[data-hook]",
|
4
|
-
:text => "<%= tab(:promotions, :url => spree.admin_promotions_path) %>",
|
4
|
+
:text => "<%= tab(:promotions, :url => spree.admin_promotions_path, :icon => 'icon-bullhorn') %>",
|
5
5
|
:disabled => false,
|
6
6
|
:original => '3e847740dc3e7f924aba1ccb4cb00c7b841649e3')
|
@@ -1,9 +1,12 @@
|
|
1
1
|
$('#actions').append('<%= escape_javascript( render(:partial => 'spree/admin/promotions/promotion_action', :object => @promotion_action) ) %>');
|
2
|
-
|
2
|
+
$('#actions .no-objects-found').hide();
|
3
3
|
initProductActions();
|
4
4
|
|
5
|
+
<% unless Rails.env.test? %>
|
6
|
+
$('.type-select.select2').select2();
|
7
|
+
<% end %>
|
8
|
+
|
5
9
|
$('#<%= dom_id @promotion_action %>').hide();
|
6
10
|
$('#<%= dom_id @promotion_action %>').fadeIn();
|
7
11
|
$('#<%= dom_id @promotion_action %> .tokeninput.products').productPicker();
|
8
|
-
$('.product_autocomplete').product_autocomplete();
|
9
|
-
|
12
|
+
$('.product_autocomplete').product_autocomplete();
|
@@ -1,2 +1 @@
|
|
1
|
-
$('#<%= dom_id @promotion_action %>').fadeOut().remove();
|
2
|
-
|
1
|
+
$('#<%= dom_id @promotion_action %>').fadeOut().remove();
|
@@ -1,7 +1,13 @@
|
|
1
1
|
$('#rules').append('<%= escape_javascript( render(:partial => 'spree/admin/promotions/promotion_rule', :object => @promotion_rule) ) %>');
|
2
|
+
$('#rules .no-objects-found').hide();
|
3
|
+
|
2
4
|
$('#<%= dom_id @promotion_rule %>').hide();
|
3
5
|
$('#<%= dom_id @promotion_rule %>').fadeIn();
|
4
6
|
$('#<%= dom_id @promotion_rule %> .tokeninput.products').productPicker();
|
5
7
|
$('#<%= dom_id @promotion_rule %> .tokeninput.users').userPicker();
|
6
8
|
|
7
9
|
$('#promotion_rule_type').html('<%= escape_javascript options_for_promotion_rule_types(@promotion) %>');
|
10
|
+
|
11
|
+
<% unless Rails.env.test? %>
|
12
|
+
$('.select_item_total.select2, .select_product.select2').select2();
|
13
|
+
<% end %>
|
@@ -1,26 +1,32 @@
|
|
1
|
-
<fieldset id="action_fields">
|
2
|
-
|
1
|
+
<fieldset id="action_fields" class="eight columns omega no-border-top">
|
2
|
+
|
3
|
+
<%= form_tag spree.admin_promotion_promotion_actions_path(@promotion), :remote => true, :id => 'new_promotion_action_form' do %>
|
4
|
+
<% options = options_for_select( Rails.application.config.spree.promotions.actions.map(&:name).map {|name| [ t("promotion_action_types.#{name.demodulize.underscore}.name"), name] } ) %>
|
5
|
+
<fieldset>
|
6
|
+
<legend align="center"><%= t(:promotion_actions) %></legend>
|
7
|
+
<div class="field">
|
8
|
+
<%= label_tag :action_type, t(:add_action_of_type)%>
|
9
|
+
<%= select_tag 'action_type', options, :class => 'select2 fullwidth' %>
|
10
|
+
</div>
|
11
|
+
<div class="filter-actions actions">
|
12
|
+
<%= button t(:add), 'icon-plus', :class => 'fullwidth' %>
|
13
|
+
</div>
|
14
|
+
</fieldset>
|
15
|
+
<% end %>
|
3
16
|
|
4
17
|
<%= form_for @promotion, :url => spree.admin_promotion_path(@promotion), :method => :put do |f| %>
|
5
18
|
<div id="actions" class="filter_list">
|
6
19
|
<% if @promotion.actions.any? %>
|
7
20
|
<%= render :partial => 'promotion_action', :collection => @promotion.actions %>
|
8
21
|
<% else %>
|
9
|
-
|
22
|
+
<div class="no-objects-found">
|
23
|
+
<%= t(:no_actions_added) %>
|
24
|
+
</div>
|
10
25
|
<% end %>
|
11
26
|
</div>
|
12
|
-
<
|
13
|
-
<%= button t(:update) %>
|
14
|
-
</
|
15
|
-
<% end %>
|
16
|
-
|
17
|
-
<%= form_tag spree.admin_promotion_promotion_actions_path(@promotion), :remote => true, :id => 'new_promotion_action_form' do %>
|
18
|
-
<% options = options_for_select( Rails.application.config.spree.promotions.actions.map(&:name).map {|name| [ t("promotion_action_types.#{name.demodulize.underscore}.name"), name] } ) %>
|
19
|
-
<p>
|
20
|
-
<%= label_tag :action_type, t(:add_action_of_type) %>
|
21
|
-
<%= select_tag 'action_type', options %>
|
22
|
-
<%= submit_tag t(:add) %>
|
23
|
-
</p>
|
27
|
+
<div class="filter-actions actions promotion-update">
|
28
|
+
<%= button t(:update), 'icon-refresh' %>
|
29
|
+
</div>
|
24
30
|
<% end %>
|
25
31
|
|
26
32
|
</fieldset>
|
@@ -1,52 +1,56 @@
|
|
1
1
|
<%= render :partial => 'spree/shared/error_messages', :locals => { :target => @promotion } %>
|
2
|
-
<
|
3
|
-
<
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
<%= f.
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
2
|
+
<div class="row">
|
3
|
+
<div id="general_fields" class="alpha thirteen columns">
|
4
|
+
<div class="alpha four columns">
|
5
|
+
<%= f.field_container :name do %>
|
6
|
+
<%= f.label :name %>
|
7
|
+
<%= f.text_field :name, :class => 'fullwidth' %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<%= f.field_container :event_name do %>
|
11
|
+
<%= f.label :event_name %>
|
12
|
+
<%= f.select :event_name, Spree::Activator.event_names.map{|name| [t("events.#{name}"), name] }, {}, {:class => 'select2 fullwidth'} %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<%= f.field_container :code do %>
|
16
|
+
<%= f.label :code %>
|
17
|
+
<%= f.text_field :code, :class => 'fullwidth' %>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<%= f.field_container :path do %>
|
21
|
+
<%= f.label :path %>
|
22
|
+
<%= f.text_field :path, :class => 'fullwidth' %>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<%= f.field_container :advertise do %>
|
26
|
+
<%= f.check_box :advertise %>
|
27
|
+
<%= f.label :advertise %>
|
28
|
+
<% end %>
|
29
|
+
</div>
|
30
|
+
|
31
|
+
<div class="omega nine columns">
|
32
|
+
<%= f.field_container :description do %>
|
33
|
+
<%= f.label :description %><br />
|
34
|
+
<%= f.text_area :description, :rows => 7, :class => 'fullwidth' %>
|
35
|
+
<% end %>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
|
39
|
+
<div id="expiry_fields" class="three columns omega">
|
40
|
+
<%= f.field_container :usage_limit do %>
|
41
|
+
<%= f.label :usage_limit %><br />
|
42
|
+
<%= f.number_field :usage_limit, :min => 0, :class => 'fullwidth' %><br>
|
43
|
+
<%= t(:current_promotion_usage, :count => @promotion.credits_count) %>
|
44
|
+
<% end %>
|
45
|
+
|
46
|
+
<div id="starts_at_field" class="field">
|
47
|
+
<%= f.label :starts_at %>
|
48
|
+
<%= f.text_field :starts_at, :class => 'datepicker datepicker-from fullwidth' %>
|
49
|
+
</div>
|
50
|
+
|
51
|
+
<div id="expires_at_field" class="field">
|
52
|
+
<%= f.label :expires_at %>
|
53
|
+
<%= f.text_field :expires_at, :class => 'datepicker datepicker-top fullwidth' %>
|
54
|
+
</div>
|
55
|
+
</div>
|
56
|
+
</div>
|
@@ -1,11 +1,11 @@
|
|
1
|
-
<div class="promotion_action <%= promotion_action.type.to_s.demodulize.underscore %>" id="<%= dom_id promotion_action %>">
|
2
|
-
<span class="delete">
|
3
|
-
<%= link_to_with_icon 'cross', '', spree.admin_promotion_promotion_action_path(@promotion, promotion_action), :remote => true, :method => :delete %>
|
4
|
-
</span>
|
1
|
+
<div class="promotion_action promotion-block <%= promotion_action.type.to_s.demodulize.underscore %>" id="<%= dom_id promotion_action %>">
|
5
2
|
<% type_name = promotion_action.class.name.demodulize.underscore %>
|
3
|
+
<h6 class="promotion-title"><%= t("promotion_action_types.#{type_name}.description") %></h6>
|
4
|
+
<%= link_to_with_icon 'icon-trash', '', spree.admin_promotion_promotion_action_path(@promotion, promotion_action), :remote => true, :method => :delete, :class => 'delete' %>
|
5
|
+
|
6
6
|
<% param_prefix = "promotion[promotion_actions_attributes][#{promotion_action.id}]" %>
|
7
7
|
<%= hidden_field_tag "#{param_prefix}[id]", promotion_action.id %>
|
8
|
-
|
8
|
+
|
9
9
|
<%= render :partial => "spree/admin/promotions/actions/#{type_name}",
|
10
10
|
:locals => { :promotion_action => promotion_action, :param_prefix => param_prefix } %>
|
11
11
|
</div>
|