spree_promo 1.0.0.rc2 → 1.0.0.rc3
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.
- data/app/assets/javascripts/admin/promotions.js +12 -3
- data/app/controllers/spree/admin/promotion_rules_controller.rb +2 -0
- data/app/controllers/spree/admin/promotions_controller.rb +2 -1
- data/app/controllers/spree/checkout_controller_decorator.rb +7 -8
- data/app/controllers/spree/content_controller_decorator.rb +3 -6
- data/app/helpers/spree/promotion_rules_helper.rb +13 -0
- data/app/models/spree/promotion/actions/create_adjustment.rb +16 -7
- data/app/models/spree/promotion/actions/create_line_items.rb +4 -1
- data/app/models/spree/promotion/rules/first_order.rb +2 -1
- data/app/models/spree/promotion.rb +29 -55
- data/app/models/spree/promotion_rule.rb +11 -0
- data/app/views/spree/admin/promotion_actions/create.js.erb +2 -1
- data/app/views/spree/admin/promotion_rules/create.js.erb +2 -0
- data/app/views/spree/admin/promotion_rules/destroy.js.erb +2 -0
- data/app/views/spree/admin/promotions/_actions.html.erb +1 -6
- data/app/views/spree/admin/promotions/_form.html.erb +5 -0
- data/app/views/spree/admin/promotions/_promotion_action.html.erb +5 -6
- data/app/views/spree/admin/promotions/_rules.html.erb +3 -3
- data/app/views/spree/admin/promotions/actions/_create_adjustment.html.erb +14 -6
- data/app/views/spree/admin/promotions/actions/_create_line_items.html.erb +2 -2
- data/config/locales/en.yml +2 -0
- data/db/migrate/20120119024707_namespace_promo_tables.rb +65 -0
- data/db/migrate/20120119024708_create_spree_pending_promotions.rb +11 -0
- data/db/migrate/20120119024721_content_visited_event.rb +29 -0
- data/lib/spree/promo/engine.rb +1 -7
- metadata +12 -11
- data/app/models/spree/promotion/rules/landing_page.rb +0 -16
- data/app/views/spree/admin/promotions/actions/_give_store_credit.html.erb +0 -6
- data/db/migrate/20111013155037_namespace_promo_tables.rb +0 -9
|
@@ -22,6 +22,8 @@ var initProductRuleSourceField = function(){
|
|
|
22
22
|
|
|
23
23
|
var initProductActions = function(){
|
|
24
24
|
|
|
25
|
+
$("#add_product_name").product_autocomplete();
|
|
26
|
+
|
|
25
27
|
$('.calculator-fields').each(function(){
|
|
26
28
|
var $fields_container = $(this);
|
|
27
29
|
var $type_select = $fields_container.find('.type-select');
|
|
@@ -43,7 +45,6 @@ var initProductActions = function(){
|
|
|
43
45
|
});
|
|
44
46
|
});
|
|
45
47
|
|
|
46
|
-
|
|
47
48
|
//
|
|
48
49
|
// CreateLineItems Promotion Action
|
|
49
50
|
//
|
|
@@ -76,7 +77,7 @@ var initProductActions = function(){
|
|
|
76
77
|
};
|
|
77
78
|
setupRemoveLineItems();
|
|
78
79
|
// Add line item to list
|
|
79
|
-
$(".promotion_action.create_line_items button.add").
|
|
80
|
+
$(".promotion_action.create_line_items button.add").unbind('click').click(function(e){
|
|
80
81
|
var $container = $(this).parents('.promotion_action');
|
|
81
82
|
var product_name = $container.find("input[name='add_product_name']").val();
|
|
82
83
|
var variant_id = $container.find("input[name='add_variant_id']").val();
|
|
@@ -86,7 +87,7 @@ var initProductActions = function(){
|
|
|
86
87
|
var newRow = "<tr><td>" + product_name + "</td><td>" + quantity + "</td><td><img src='/assets/admin/icons/cross.png' /></td></tr>";
|
|
87
88
|
$container.find('table').append(newRow);
|
|
88
89
|
// Add to serialized string in hidden text field
|
|
89
|
-
var $hiddenField = $container.find("
|
|
90
|
+
var $hiddenField = $container.find(".line_items_string");
|
|
90
91
|
$hiddenField.val($hiddenField.val() + "," + variant_id + "x" + quantity);
|
|
91
92
|
setupRemoveLineItems();
|
|
92
93
|
hideOrShowItemTables();
|
|
@@ -101,6 +102,14 @@ var initProductActions = function(){
|
|
|
101
102
|
$(document).ready(function() {
|
|
102
103
|
initProductRuleSourceField();
|
|
103
104
|
initProductActions();
|
|
105
|
+
|
|
106
|
+
// toggle fields for specific events
|
|
107
|
+
$('#promotion_event_name').change(function() {
|
|
108
|
+
$('#promotion_code_field').toggle($('#promotion_event_name').val() == 'spree.checkout.coupon_code_added');
|
|
109
|
+
$('#promotion_path_field').toggle($('#promotion_event_name').val() == 'spree.content.visited');
|
|
110
|
+
});
|
|
111
|
+
$('#promotion_event_name').change();
|
|
112
|
+
|
|
104
113
|
});
|
|
105
114
|
|
|
106
115
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
class Spree::Admin::PromotionRulesController < Spree::Admin::BaseController
|
|
2
|
+
helper 'spree/promotion_rules'
|
|
3
|
+
|
|
2
4
|
def create
|
|
3
5
|
@promotion = Spree::Promotion.find(params[:promotion_id])
|
|
4
6
|
@promotion_rule = params[:promotion_rule][:type].constantize.new(params[:promotion_rule])
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
Spree::CheckoutController.class_eval do
|
|
2
|
+
|
|
3
|
+
#TODO 90% of this method is duplicated code. DRY
|
|
2
4
|
def update
|
|
3
5
|
if @order.update_attributes(object_params)
|
|
4
6
|
|
|
5
7
|
fire_event('spree.checkout.update')
|
|
6
8
|
|
|
7
9
|
if @order.coupon_code.present?
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
#
|
|
11
|
-
# TODO: The ActiveRecord::Base.connection.quote_column_name stuff is a bit long...
|
|
12
|
-
# TODO: Is there a better way to do that?
|
|
13
|
-
if Spree::Preference.where(:value => @order.coupon_code).where("#{ActiveRecord::Base.connection.quote_column_name("key")} LIKE 'spree/promotion/code/%'").present?
|
|
10
|
+
|
|
11
|
+
if Spree::Promotion.exists?(:code => @order.coupon_code)
|
|
14
12
|
fire_event('spree.checkout.coupon_code_added', :coupon_code => @order.coupon_code)
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
# If it doesn't exist, raise an error!
|
|
14
|
+
# Giving them another chance to enter a valid coupon code
|
|
17
15
|
else
|
|
18
16
|
flash[:error] = t(:promotion_not_found)
|
|
19
17
|
render :edit and return
|
|
@@ -39,4 +37,5 @@ Spree::CheckoutController.class_eval do
|
|
|
39
37
|
respond_with(@order) { |format| format.html { render :edit } }
|
|
40
38
|
end
|
|
41
39
|
end
|
|
40
|
+
|
|
42
41
|
end
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
# Keep a record ot all static page paths visited for promotions that require them
|
|
2
1
|
Spree::ContentController.class_eval do
|
|
3
|
-
after_filter :
|
|
2
|
+
after_filter :fire_visited_event
|
|
4
3
|
|
|
5
|
-
def
|
|
6
|
-
|
|
7
|
-
path = "content/#{params[:action]}"
|
|
8
|
-
session[:visited_paths] = (session[:visited_paths] << path).compact.uniq
|
|
4
|
+
def fire_visited_event
|
|
5
|
+
fire_event('spree.content.visited', :path => path = "content/#{params[:action]}")
|
|
9
6
|
end
|
|
10
7
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module PromotionRulesHelper
|
|
3
|
+
|
|
4
|
+
def options_for_promotion_rule_types(promotion)
|
|
5
|
+
existing = promotion.rules.map { |rule| rule.class.name }
|
|
6
|
+
rule_names = Rails.application.config.spree.promotions.rules.map(&:name).reject{ |r| existing.include? r }
|
|
7
|
+
options = rule_names.map { |name| [ t("promotion_rule_types.#{name.demodulize.underscore}.name"), name] }
|
|
8
|
+
options_for_select(options)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
@@ -10,13 +10,22 @@ module Spree
|
|
|
10
10
|
return unless order = options[:order]
|
|
11
11
|
# Nothing to do if the promotion is already associated with the order
|
|
12
12
|
return if order.promotion_credit_exists?(promotion)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
|
|
14
|
+
order.adjustments.promotion.reload.clear
|
|
15
|
+
order.update!
|
|
16
|
+
create_adjustment("#{I18n.t(:promotion)} (#{promotion.name})", order, order)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# override of CalculatedAdjustments#create_adjustment so promotional
|
|
20
|
+
# adjustments are added all the time. They will get their eligability
|
|
21
|
+
# set to false if the amount is 0
|
|
22
|
+
def create_adjustment(label, target, calculable, mandatory=false)
|
|
23
|
+
amount = compute_amount(calculable)
|
|
24
|
+
target.adjustments.create(:amount => amount,
|
|
25
|
+
:source => calculable,
|
|
26
|
+
:originator => self,
|
|
27
|
+
:label => label,
|
|
28
|
+
:mandatory => mandatory)
|
|
20
29
|
end
|
|
21
30
|
|
|
22
31
|
# Ensure a negative amount which does not exceed the sum of the order's item_total and ship_total
|
|
@@ -7,7 +7,10 @@ module Spree
|
|
|
7
7
|
def perform(options = {})
|
|
8
8
|
return unless order = options[:order]
|
|
9
9
|
promotion_action_line_items.each do |item|
|
|
10
|
-
order.
|
|
10
|
+
current_quantity = order.quantity_of(item.variant)
|
|
11
|
+
if current_quantity < item.quantity
|
|
12
|
+
order.add_variant(item.variant, item.quantity - current_quantity)
|
|
13
|
+
end
|
|
11
14
|
end
|
|
12
15
|
end
|
|
13
16
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class Promotion::Rules::FirstOrder < PromotionRule
|
|
3
3
|
def eligible?(order, options = {})
|
|
4
|
-
|
|
4
|
+
user = order.try(:user) || options[:user]
|
|
5
|
+
!!(user && user.orders.complete.count == 0)
|
|
5
6
|
end
|
|
6
7
|
end
|
|
7
8
|
end
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
class Promotion < Spree::Activator
|
|
3
3
|
MATCH_POLICIES = %w(all any)
|
|
4
|
+
UNACTIVATABLE_ORDER_STATES = ["complete", "awaiting_return", "returned"]
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
preference :code, :string
|
|
8
|
-
preference :advertise, :boolean, :default => false
|
|
9
|
-
|
|
10
|
-
[:usage_limit, :match_policy, :code, :advertise].each do |field|
|
|
11
|
-
alias_method field, "preferred_#{field}"
|
|
12
|
-
alias_method "#{field}=", "preferred_#{field}="
|
|
13
|
-
end
|
|
6
|
+
Activator.event_names << 'spree.checkout.coupon_code_added'
|
|
7
|
+
Activator.event_names << 'spree.content.visited'
|
|
14
8
|
|
|
15
9
|
has_many :promotion_rules, :foreign_key => 'activator_id', :autosave => true, :dependent => :destroy
|
|
16
10
|
alias_method :rules, :promotion_rules
|
|
@@ -20,8 +14,6 @@ module Spree
|
|
|
20
14
|
alias_method :actions, :promotion_actions
|
|
21
15
|
accepts_nested_attributes_for :promotion_actions
|
|
22
16
|
|
|
23
|
-
after_create :update_preferences
|
|
24
|
-
|
|
25
17
|
# TODO: This shouldn't be necessary with :autosave option but nested attribute updating of actions is broken without it
|
|
26
18
|
after_save :save_rules_and_actions
|
|
27
19
|
def save_rules_and_actions
|
|
@@ -29,24 +21,9 @@ module Spree
|
|
|
29
21
|
end
|
|
30
22
|
|
|
31
23
|
validates :name, :presence => true
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
method_name = pref.to_sym
|
|
36
|
-
define_method method_name do
|
|
37
|
-
get_preference(pref.to_sym)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
method_name = "#{pref}=".to_sym
|
|
41
|
-
define_method method_name do |value|
|
|
42
|
-
unless new_record?
|
|
43
|
-
pref = value
|
|
44
|
-
else
|
|
45
|
-
@preferences_hash ||= {}
|
|
46
|
-
@preferences_hash[pref.to_sym] = value
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
24
|
+
validates :code, :presence => true, :if => lambda{|r| r.event_name == 'spree.checkout.coupon_code_added' }
|
|
25
|
+
validates :path, :presence => true, :if => lambda{|r| r.event_name == 'spree.content.visited' }
|
|
26
|
+
validates :usage_limit, :numericality => { :greater_than => 0, :allow_nil => true }
|
|
50
27
|
|
|
51
28
|
class << self
|
|
52
29
|
def advertised
|
|
@@ -67,28 +44,30 @@ module Spree
|
|
|
67
44
|
end
|
|
68
45
|
|
|
69
46
|
def activate(payload)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
end
|
|
47
|
+
return unless order_activatable? payload[:order]
|
|
48
|
+
|
|
49
|
+
if code.present?
|
|
50
|
+
event_code = payload[:coupon_code].to_s.strip.downcase
|
|
51
|
+
return unless event_code == self.code.to_s.strip.downcase
|
|
76
52
|
end
|
|
77
|
-
end
|
|
78
53
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
54
|
+
if path.present?
|
|
55
|
+
return unless path == payload[:path]
|
|
56
|
+
end
|
|
82
57
|
|
|
83
|
-
|
|
84
|
-
|
|
58
|
+
actions.each do |action|
|
|
59
|
+
action.perform(payload)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
85
62
|
|
|
86
|
-
|
|
63
|
+
# called anytime order.update! happens
|
|
64
|
+
def eligible?(order)
|
|
65
|
+
return false if expired? || usage_limit_exceeded?(order)
|
|
66
|
+
rules_are_eligible?(order, {})
|
|
87
67
|
end
|
|
88
68
|
|
|
89
69
|
def rules_are_eligible?(order, options = {})
|
|
90
70
|
return true if rules.none?
|
|
91
|
-
|
|
92
71
|
eligible = lambda { |r| r.eligible?(order, options) }
|
|
93
72
|
if match_policy == 'all'
|
|
94
73
|
rules.all?(&eligible)
|
|
@@ -97,13 +76,19 @@ module Spree
|
|
|
97
76
|
end
|
|
98
77
|
end
|
|
99
78
|
|
|
79
|
+
def order_activatable?(order)
|
|
80
|
+
order &&
|
|
81
|
+
created_at.to_i < order.created_at.to_i &&
|
|
82
|
+
!UNACTIVATABLE_ORDER_STATES.include?(order.state)
|
|
83
|
+
end
|
|
84
|
+
|
|
100
85
|
# Products assigned to all product rules
|
|
101
86
|
def products
|
|
102
87
|
@products ||= rules.of_type('Promotion::Rules::Product').map(&:products).flatten.uniq
|
|
103
88
|
end
|
|
104
89
|
|
|
105
90
|
def usage_limit_exceeded?(order = nil)
|
|
106
|
-
|
|
91
|
+
usage_limit.present? && usage_limit > 0 && adjusted_credits_count(order) >= usage_limit
|
|
107
92
|
end
|
|
108
93
|
|
|
109
94
|
def adjusted_credits_count(order)
|
|
@@ -119,16 +104,5 @@ module Spree
|
|
|
119
104
|
credits.count
|
|
120
105
|
end
|
|
121
106
|
|
|
122
|
-
|
|
123
|
-
private
|
|
124
|
-
|
|
125
|
-
def update_preferences
|
|
126
|
-
if @preferences_hash.present? && !@preferences_hash.empty?
|
|
127
|
-
@preferences_hash.each do |key, value|
|
|
128
|
-
pref_key = "spree/promotion/#{key}/#{self.id}"
|
|
129
|
-
Spree::Preference.create(:value => value, :key => pref_key)
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
107
|
end
|
|
134
108
|
end
|
|
@@ -5,8 +5,19 @@ module Spree
|
|
|
5
5
|
|
|
6
6
|
scope :of_type, lambda {|t| {:conditions => {:type => t}}}
|
|
7
7
|
|
|
8
|
+
validate :promotion, :presence => true
|
|
9
|
+
validate :unique_per_activator, :on => :create
|
|
10
|
+
|
|
8
11
|
def eligible?(order, options = {})
|
|
9
12
|
raise 'eligible? should be implemented in a sub-class of Promotion::PromotionRule'
|
|
10
13
|
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
def unique_per_activator
|
|
17
|
+
if Spree::PromotionRule.exists?(:activator_id => activator_id, :type => self.class.name)
|
|
18
|
+
errors[:base] << "Promotion already contains this rule type"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
11
22
|
end
|
|
12
23
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
$('#
|
|
1
|
+
$('#actions').append('<%= escape_javascript( render(:partial => 'spree/admin/promotions/promotion_action', :object => @promotion_action) ) %>');
|
|
2
|
+
|
|
2
3
|
initProductActions();
|
|
3
4
|
|
|
4
5
|
$('#<%= dom_id @promotion_action %>').hide();
|
|
@@ -4,3 +4,5 @@ $('#<%= dom_id @promotion_rule %>').fadeIn();
|
|
|
4
4
|
initProductRuleSourceField();
|
|
5
5
|
$('#<%= dom_id @promotion_rule %> .tokeninput.products').productPicker();
|
|
6
6
|
$('#<%= dom_id @promotion_rule %> .tokeninput.users').userPicker();
|
|
7
|
+
|
|
8
|
+
$('#promotion_rule_type').html('<%= escape_javascript options_for_promotion_rule_types(@promotion) %>');
|
|
@@ -4,12 +4,7 @@
|
|
|
4
4
|
<%= form_for @promotion, :url => spree.admin_promotion_path(@promotion), :method => :put do |f| %>
|
|
5
5
|
<div id="actions" class="filter_list">
|
|
6
6
|
<% if @promotion.actions.any? %>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
<%= f.fields_for :promotion_actions do |action_form| %>
|
|
10
|
-
<%= render :partial => 'spree/admin/promotions/promotion_action', :locals => { :action_form => action_form } %>
|
|
11
|
-
<% end %>
|
|
12
|
-
|
|
7
|
+
<%= render :partial => 'promotion_action', :collection => @promotion.actions %>
|
|
13
8
|
<% else %>
|
|
14
9
|
<!-- <p><%= t(:no_actions_added) %></p> -->
|
|
15
10
|
<% end %>
|
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
<%= f.text_field :code %>
|
|
17
17
|
<% end %>
|
|
18
18
|
|
|
19
|
+
<%= f.field_container :path do %>
|
|
20
|
+
<%= f.label :path, t(:path) %><br />
|
|
21
|
+
<%= f.text_field :path %>
|
|
22
|
+
<% end %>
|
|
23
|
+
|
|
19
24
|
<%= f.field_container :description do %>
|
|
20
25
|
<%= f.label :description %><br />
|
|
21
26
|
<%= f.text_area :description, :style => 'height:50px;' %>
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
<div class="promotion_action <%= promotion_action.type.demodulize.underscore %>" id="<%= dom_id promotion_action %>">
|
|
1
|
+
<div class="promotion_action <%= promotion_action.type.to_s.demodulize.underscore %>" id="<%= dom_id promotion_action %>">
|
|
3
2
|
<span class="delete">
|
|
4
3
|
<%= link_to_with_icon 'cross', '', spree.admin_promotion_promotion_action_path(@promotion, promotion_action), :remote => true, :method => :delete %>
|
|
5
4
|
</span>
|
|
6
5
|
<% type_name = promotion_action.class.name.demodulize.underscore %>
|
|
7
6
|
<% param_prefix = "promotion[promotion_actions_attributes][#{promotion_action.id}]" %>
|
|
8
|
-
|
|
7
|
+
<%= hidden_field_tag "#{param_prefix}[id]", promotion_action.id %>
|
|
9
8
|
<p><%= t("promotion_action_types.#{type_name}.description") %></p>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
</div>
|
|
9
|
+
<%= render :partial => "spree/admin/promotions/actions/#{type_name}",
|
|
10
|
+
:locals => { :promotion_action => promotion_action, :param_prefix => param_prefix } %>
|
|
11
|
+
</div>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<%= form_for @promotion, :url => object_url, :method => :put do |f| %>
|
|
5
5
|
<p>
|
|
6
6
|
<% Spree::Promotion::MATCH_POLICIES.each do |policy| %>
|
|
7
|
-
<label><%= f.radio_button :
|
|
7
|
+
<label><%= f.radio_button :match_policy, policy %> <%= t "promotion_form.match_policies.#{policy}" %></label>
|
|
8
8
|
<% end %>
|
|
9
9
|
</p>
|
|
10
10
|
<div id="rules" class="filter_list">
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
|
|
22
22
|
<%= form_tag spree.admin_promotion_promotion_rules_path(@promotion), :remote => true,
|
|
23
23
|
:id => 'new_product_rule_form' do %>
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
<p>
|
|
26
26
|
<%= label_tag :promotion_rule_type, t(:add_rule_of_type) %>
|
|
27
|
-
<%= select_tag('promotion_rule[type]',
|
|
27
|
+
<%= select_tag('promotion_rule[type]', options_for_promotion_rule_types(@promotion)) %>
|
|
28
28
|
<%= submit_tag t(:add) %>
|
|
29
29
|
</p>
|
|
30
30
|
<% end %>
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
<div class="calculator-fields">
|
|
2
2
|
|
|
3
3
|
<p class="field">
|
|
4
|
-
|
|
5
|
-
<%=
|
|
4
|
+
<% field_name = "#{param_prefix}[calculator_type]" %>
|
|
5
|
+
<%= label_tag field_name, t(:calculator) %>
|
|
6
|
+
<%= select_tag field_name,
|
|
7
|
+
options_from_collection_for_select(@calculators, :to_s, :description, promotion_action.calculator.type),
|
|
8
|
+
:class => 'type-select' %>
|
|
6
9
|
<% if promotion_action.calculator.respond_to?(:preferences) %>
|
|
7
10
|
<span class="warning"><%= t(:calculator_settings_warning) %></span>
|
|
8
11
|
<% end %>
|
|
@@ -10,10 +13,15 @@
|
|
|
10
13
|
|
|
11
14
|
<% unless promotion_action.new_record? %>
|
|
12
15
|
<div class="settings">
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
<% promotion_action.calculator.preferences.keys.map do |key| %>
|
|
17
|
+
<% field_name = "#{param_prefix}[calculator_attributes][preferred_#{key}]" %>
|
|
18
|
+
<%= label_tag field_name, key.to_s.titleize %>
|
|
19
|
+
<%= preference_field_tag(field_name,
|
|
20
|
+
promotion_action.calculator.get_preference(key),
|
|
21
|
+
:type => promotion_action.calculator.preference_type(key)) %>
|
|
22
|
+
<% end %>
|
|
23
|
+
<%= hidden_field_tag "#{param_prefix}[calculator_attributes][id]", promotion_action.calculator.id %>
|
|
16
24
|
</div>
|
|
17
25
|
<% end %>
|
|
18
26
|
|
|
19
|
-
</div>
|
|
27
|
+
</div>
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
<% end %>
|
|
20
20
|
</table>
|
|
21
21
|
|
|
22
|
-
<%=
|
|
22
|
+
<%= hidden_field_tag "#{param_prefix}[line_items_string]", promotion_action.line_items_string,
|
|
23
|
+
:class => 'line_items_string' %>
|
|
23
24
|
|
|
24
25
|
<div class="add-line-item">
|
|
25
26
|
<fieldset>
|
|
@@ -38,6 +39,5 @@
|
|
|
38
39
|
<br />
|
|
39
40
|
<button class="add small"> <%= t(:add) %></button>
|
|
40
41
|
</div>
|
|
41
|
-
|
|
42
42
|
</fieldset>
|
|
43
43
|
</div>
|
data/config/locales/en.yml
CHANGED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
class NamespacePromoTables < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
# namespace promo tables
|
|
4
|
+
rename_table :promotion_actions, :spree_promotion_actions
|
|
5
|
+
rename_table :promotion_rules, :spree_promotion_rules
|
|
6
|
+
rename_table :promotion_rules_users, :spree_promotion_rules_users
|
|
7
|
+
rename_table :promotion_action_line_items, :spree_promotion_action_line_items
|
|
8
|
+
rename_table :products_promotion_rules, :spree_products_promotion_rules
|
|
9
|
+
|
|
10
|
+
# add old promo preferences as columns
|
|
11
|
+
add_column :spree_activators, :usage_limit, :integer
|
|
12
|
+
add_column :spree_activators, :match_policy, :string, :default => 'all'
|
|
13
|
+
add_column :spree_activators, :code, :string
|
|
14
|
+
add_column :spree_activators, :advertise, :boolean, :default => false
|
|
15
|
+
|
|
16
|
+
Spree::Promotion.class_eval do
|
|
17
|
+
preference :usage_limit, :integer
|
|
18
|
+
preference :match_policy, :string, :default => 'all'
|
|
19
|
+
preference :code, :string
|
|
20
|
+
preference :advertise, :boolean, :default => false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# manually update old promotions to use the new promotion style
|
|
24
|
+
Spree::Preference.where(:owner_type => 'Spree::Activator').group_by(&:owner_id).each do |key, pref_group|
|
|
25
|
+
@promo = Spree::Promotion.new
|
|
26
|
+
pref_group.each do |pref|
|
|
27
|
+
case pref.name
|
|
28
|
+
when 'code'
|
|
29
|
+
@promo.code = pref.value.to_s
|
|
30
|
+
@promo.name = pref.value.to_s
|
|
31
|
+
when 'advertise'
|
|
32
|
+
@promo.advertise = pref.value
|
|
33
|
+
when 'usage_limit'
|
|
34
|
+
@promo.usage_limit = pref.value
|
|
35
|
+
when 'match_policy'
|
|
36
|
+
@promo.match_policy = pref.value
|
|
37
|
+
end
|
|
38
|
+
@promo.event_name = Spree::Promotion.find(pref.owner_id).event_name
|
|
39
|
+
end
|
|
40
|
+
@promo.save!
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Remove old promotions
|
|
44
|
+
Spree::Promotion.where(:code => nil).delete_all
|
|
45
|
+
|
|
46
|
+
# This *should* be in the new_preferences migration inside of Core but...
|
|
47
|
+
# This is migration needs to have these keys around so that
|
|
48
|
+
# we can convert the promotions over correctly.
|
|
49
|
+
# So they hang around until we're *finally* done with them, since promo's
|
|
50
|
+
# migrations are copied over *after* core, and then we ditch them.
|
|
51
|
+
remove_column :spree_preferences, :name
|
|
52
|
+
remove_column :spree_preferences, :owner_id
|
|
53
|
+
remove_column :spree_preferences, :owner_type
|
|
54
|
+
remove_column :spree_preferences, :group_id
|
|
55
|
+
remove_column :spree_preferences, :group_type
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.down
|
|
59
|
+
rename_table :spree_promotion_actions, :promotion_actions
|
|
60
|
+
rename_table :spree_promotion_rules, :promotion_rules
|
|
61
|
+
rename_table :spree_promotion_rules_users, :promotion_rules_users
|
|
62
|
+
rename_table :spree_promotion_action_line_items, :promotion_action_line_items
|
|
63
|
+
rename_table :spree_products_promotion_rules, :products_promotion_rules
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
class CreateSpreePendingPromotions < ActiveRecord::Migration
|
|
2
|
+
def change
|
|
3
|
+
create_table :spree_pending_promotions do |t|
|
|
4
|
+
t.references :user
|
|
5
|
+
t.references :promotion
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
add_index :spree_pending_promotions, :user_id
|
|
9
|
+
add_index :spree_pending_promotions, :promotion_id
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# LandingPage used to support static pages, we've moved to a static
|
|
2
|
+
# event. This adds path to promotions then migrates the old LandingPage rules
|
|
3
|
+
class ContentVisitedEvent < ActiveRecord::Migration
|
|
4
|
+
|
|
5
|
+
# Removed Class for Migrations
|
|
6
|
+
class Spree::Promotion::Rules::LandingPage < Spree::PromotionRule
|
|
7
|
+
preference :path, :string
|
|
8
|
+
def eligible?(order, options = {})
|
|
9
|
+
true
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def up
|
|
14
|
+
add_column :spree_activators, :path, :string
|
|
15
|
+
|
|
16
|
+
Spree::Promotion::Rules::LandingPage.all.each do |promotion_rule|
|
|
17
|
+
promotion = promotion_rule.promotion
|
|
18
|
+
say "migrating #{promotion.name} promotion to use 'spree.content.visited' event"
|
|
19
|
+
promotion.event_name = 'spree.content.visited'
|
|
20
|
+
promotion.path = promotion_rule.preferred_path
|
|
21
|
+
promotion.promotion_rules.delete promotion_rule
|
|
22
|
+
promotion.save(:validate => false)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def down
|
|
27
|
+
remove_column :spree_activators, :path
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/spree/promo/engine.rb
CHANGED
|
@@ -13,12 +13,6 @@ module Spree
|
|
|
13
13
|
Rails.configuration.cache_classes ? require(c) : load(c)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
# Include list of visited paths in notification payload hash
|
|
17
|
-
Spree::Core::ControllerHelpers::InstanceMethods.class_eval do
|
|
18
|
-
def default_notification_payload
|
|
19
|
-
{ :user => current_user, :order => current_order, :visited_paths => session[:visited_paths] }
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
16
|
end
|
|
23
17
|
|
|
24
18
|
config.autoload_paths += %W(#{config.root}/lib)
|
|
@@ -46,7 +40,6 @@ module Spree
|
|
|
46
40
|
Spree::Promotion::Rules::Product,
|
|
47
41
|
Spree::Promotion::Rules::User,
|
|
48
42
|
Spree::Promotion::Rules::FirstOrder,
|
|
49
|
-
Spree::Promotion::Rules::LandingPage,
|
|
50
43
|
Spree::Promotion::Rules::UserLoggedIn]
|
|
51
44
|
end
|
|
52
45
|
|
|
@@ -54,6 +47,7 @@ module Spree
|
|
|
54
47
|
app.config.spree.promotions.actions = [Spree::Promotion::Actions::CreateAdjustment,
|
|
55
48
|
Spree::Promotion::Actions::CreateLineItems]
|
|
56
49
|
end
|
|
50
|
+
|
|
57
51
|
end
|
|
58
52
|
end
|
|
59
53
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_promo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.0.
|
|
4
|
+
version: 1.0.0.rc3
|
|
5
5
|
prerelease: 6
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,30 +9,30 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-01-
|
|
12
|
+
date: 2012-01-31 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: spree_core
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &70260369514180 !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - =
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: 1.0.0.
|
|
21
|
+
version: 1.0.0.rc3
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
|
-
version_requirements: *
|
|
24
|
+
version_requirements: *70260369514180
|
|
25
25
|
- !ruby/object:Gem::Dependency
|
|
26
26
|
name: spree_auth
|
|
27
|
-
requirement: &
|
|
27
|
+
requirement: &70260369513500 !ruby/object:Gem::Requirement
|
|
28
28
|
none: false
|
|
29
29
|
requirements:
|
|
30
30
|
- - =
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 1.0.0.
|
|
32
|
+
version: 1.0.0.rc3
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
|
-
version_requirements: *
|
|
35
|
+
version_requirements: *70260369513500
|
|
36
36
|
description: Required dependency for Spree
|
|
37
37
|
email: david@spreecommerce.com
|
|
38
38
|
executables: []
|
|
@@ -52,6 +52,7 @@ files:
|
|
|
52
52
|
- app/controllers/spree/checkout_controller_decorator.rb
|
|
53
53
|
- app/controllers/spree/content_controller_decorator.rb
|
|
54
54
|
- app/controllers/spree/orders_controller_decorator.rb
|
|
55
|
+
- app/helpers/spree/promotion_rules_helper.rb
|
|
55
56
|
- app/models/spree/adjustment_decorator.rb
|
|
56
57
|
- app/models/spree/calculator/free_shipping.rb
|
|
57
58
|
- app/models/spree/order_decorator.rb
|
|
@@ -61,7 +62,6 @@ files:
|
|
|
61
62
|
- app/models/spree/promotion/actions/create_line_items.rb
|
|
62
63
|
- app/models/spree/promotion/rules/first_order.rb
|
|
63
64
|
- app/models/spree/promotion/rules/item_total.rb
|
|
64
|
-
- app/models/spree/promotion/rules/landing_page.rb
|
|
65
65
|
- app/models/spree/promotion/rules/product.rb
|
|
66
66
|
- app/models/spree/promotion/rules/user.rb
|
|
67
67
|
- app/models/spree/promotion/rules/user_logged_in.rb
|
|
@@ -84,7 +84,6 @@ files:
|
|
|
84
84
|
- app/views/spree/admin/promotions/_tab.html.erb
|
|
85
85
|
- app/views/spree/admin/promotions/actions/_create_adjustment.html.erb
|
|
86
86
|
- app/views/spree/admin/promotions/actions/_create_line_items.html.erb
|
|
87
|
-
- app/views/spree/admin/promotions/actions/_give_store_credit.html.erb
|
|
88
87
|
- app/views/spree/admin/promotions/edit.html.erb
|
|
89
88
|
- app/views/spree/admin/promotions/index.html.erb
|
|
90
89
|
- app/views/spree/admin/promotions/new.html.erb
|
|
@@ -112,7 +111,9 @@ files:
|
|
|
112
111
|
- db/migrate/20110331094351_promotion_changes_to_subclass_of_activator.rb
|
|
113
112
|
- db/migrate/20110404123358_create_promotion_actions.rb
|
|
114
113
|
- db/migrate/20110601202923_create_promotion_action_line_items.rb
|
|
115
|
-
- db/migrate/
|
|
114
|
+
- db/migrate/20120119024707_namespace_promo_tables.rb
|
|
115
|
+
- db/migrate/20120119024708_create_spree_pending_promotions.rb
|
|
116
|
+
- db/migrate/20120119024721_content_visited_event.rb
|
|
116
117
|
homepage: http://spreecommerce.com
|
|
117
118
|
licenses: []
|
|
118
119
|
post_install_message:
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# A rule to limit a promotion to a specific user.
|
|
2
|
-
module Spree
|
|
3
|
-
class Promotion::Rules::LandingPage < PromotionRule
|
|
4
|
-
preference :path, :string
|
|
5
|
-
|
|
6
|
-
def eligible?(order, options = {})
|
|
7
|
-
if options.has_key?(:visited_paths)
|
|
8
|
-
options[:visited_paths].to_a.any? do |path|
|
|
9
|
-
path == preferred_path
|
|
10
|
-
end
|
|
11
|
-
else
|
|
12
|
-
true
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
class NamespacePromoTables < ActiveRecord::Migration
|
|
2
|
-
def change
|
|
3
|
-
rename_table :promotion_actions, :spree_promotion_actions
|
|
4
|
-
rename_table :promotion_rules, :spree_promotion_rules
|
|
5
|
-
rename_table :promotion_rules_users, :spree_promotion_rules_users
|
|
6
|
-
rename_table :promotion_action_line_items, :spree_promotion_action_line_items
|
|
7
|
-
rename_table :products_promotion_rules, :spree_products_promotion_rules
|
|
8
|
-
end
|
|
9
|
-
end
|