spree_promo 1.0.0.rc2 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. data/app/assets/javascripts/admin/promotions.js +12 -3
  2. data/app/controllers/spree/admin/promotion_rules_controller.rb +2 -0
  3. data/app/controllers/spree/admin/promotions_controller.rb +2 -1
  4. data/app/controllers/spree/checkout_controller_decorator.rb +7 -8
  5. data/app/controllers/spree/content_controller_decorator.rb +3 -6
  6. data/app/helpers/spree/promotion_rules_helper.rb +13 -0
  7. data/app/models/spree/promotion/actions/create_adjustment.rb +16 -7
  8. data/app/models/spree/promotion/actions/create_line_items.rb +4 -1
  9. data/app/models/spree/promotion/rules/first_order.rb +2 -1
  10. data/app/models/spree/promotion.rb +29 -55
  11. data/app/models/spree/promotion_rule.rb +11 -0
  12. data/app/views/spree/admin/promotion_actions/create.js.erb +2 -1
  13. data/app/views/spree/admin/promotion_rules/create.js.erb +2 -0
  14. data/app/views/spree/admin/promotion_rules/destroy.js.erb +2 -0
  15. data/app/views/spree/admin/promotions/_actions.html.erb +1 -6
  16. data/app/views/spree/admin/promotions/_form.html.erb +5 -0
  17. data/app/views/spree/admin/promotions/_promotion_action.html.erb +5 -6
  18. data/app/views/spree/admin/promotions/_rules.html.erb +3 -3
  19. data/app/views/spree/admin/promotions/actions/_create_adjustment.html.erb +14 -6
  20. data/app/views/spree/admin/promotions/actions/_create_line_items.html.erb +2 -2
  21. data/config/locales/en.yml +2 -0
  22. data/db/migrate/20120119024707_namespace_promo_tables.rb +65 -0
  23. data/db/migrate/20120119024708_create_spree_pending_promotions.rb +11 -0
  24. data/db/migrate/20120119024721_content_visited_event.rb +29 -0
  25. data/lib/spree/promo/engine.rb +1 -7
  26. metadata +12 -11
  27. data/app/models/spree/promotion/rules/landing_page.rb +0 -16
  28. data/app/views/spree/admin/promotions/actions/_give_store_credit.html.erb +0 -6
  29. 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").live('click',function(e){
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("input[type='hidden']");
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])
@@ -2,6 +2,7 @@ module Spree
2
2
  module Admin
3
3
  class PromotionsController < ResourceController
4
4
  before_filter :load_data
5
+ helper 'spree/promotion_rules'
5
6
 
6
7
  protected
7
8
  def build_resource
@@ -21,4 +22,4 @@ module Spree
21
22
  end
22
23
  end
23
24
  end
24
- end
25
+ end
@@ -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
- # Promotion codes are stored in the preference table
9
- # Therefore we need to do a lookup there and find if one exists
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
- # If it doesn't exist, raise an error!
16
- # Giving them another chance to enter a valid coupon code
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 :store_visited_path
2
+ after_filter :fire_visited_event
4
3
 
5
- def store_visited_path
6
- session[:visited_paths] ||= []
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
- if amount = calculator.compute(order)
14
- amount = BigDecimal.new(amount.to_s)
15
- amount = order.item_total if amount > order.item_total
16
- order.adjustments.promotion.reload.clear
17
- order.update!
18
- create_adjustment("#{I18n.t(:promotion)} (#{promotion.name})", order, order)
19
- end
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.add_variant(item.variant, item.quantity)
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
- order.user && order.user.orders.complete.count == 0
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
- preference :usage_limit, :integer
6
- preference :match_policy, :string, :default => MATCH_POLICIES.first
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
- #validates :preferred_code, :presence => true, :if => lambda{|r| r.event_name == 'spree.checkout.coupon_code_added' }
33
-
34
- %w(usage_limit match_policy code advertise).each do |pref|
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
- # Since multiple promotions could be listening we need to make sure the
71
- # event applies to this one.
72
- if eligible?(payload[:order], payload)
73
- actions.each do |action|
74
- action.perform(payload)
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
- # Whether the promotion is eligible for this particular order.
80
- def eligible?(order, options = {})
81
- return false if expired? || usage_limit_exceeded?(order)
54
+ if path.present?
55
+ return unless path == payload[:path]
56
+ end
82
57
 
83
- event_code = options[:coupon_code].to_s.strip.downcase
84
- return false unless event_code == self.code.to_s.strip.downcase
58
+ actions.each do |action|
59
+ action.perform(payload)
60
+ end
61
+ end
85
62
 
86
- rules_are_eligible?(order, options)
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
- preferred_usage_limit.present? && preferred_usage_limit.to_i > 0 && adjusted_credits_count(order) >= preferred_usage_limit.to_i
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
- $('#actions_container').html('<%= escape_javascript( render(:partial => 'spree/admin/promotions/actions') ) %>');
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) %>');
@@ -1 +1,3 @@
1
1
  $('#<%= dom_id @promotion_rule %>').fadeOut().remove();
2
+ $('#promotion_rule_type').html('<%= escape_javascript options_for_promotion_rule_types(@promotion) %>');
3
+
@@ -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
- <%#= render :partial => 'promotion_action', :collection => @promotion.actions, :locals => {:f => f} %>
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
- <% promotion_action = action_form.object %>
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
- <%#= hidden_field_tag "#{param_prefix}[id]", promotion_action.id %>
7
+ <%= hidden_field_tag "#{param_prefix}[id]", promotion_action.id %>
9
8
  <p><%= t("promotion_action_types.#{type_name}.description") %></p>
10
-
11
- <%= render :partial => "spree/admin/promotions/actions/#{type_name}", :locals => { :action_form => action_form, :promotion_action => promotion_action, :param_prefix => param_prefix } %>
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 :preferred_match_policy, policy %> <%= t "promotion_form.match_policies.#{policy}" %></label> &nbsp;
7
+ <label><%= f.radio_button :match_policy, policy %> <%= t "promotion_form.match_policies.#{policy}" %></label> &nbsp;
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
- <% options = options_for_select( Rails.application.config.spree.promotions.rules.map(&:name).map {|name| [ t("promotion_rule_types.#{name.demodulize.underscore}.name"), name] } ) %>
24
+
25
25
  <p>
26
26
  <%= label_tag :promotion_rule_type, t(:add_rule_of_type) %>
27
- <%= select_tag('promotion_rule[type]', options) %>
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
- <%= action_form.label :calculator_type, t(:calculator) %>
5
- <%= action_form.collection_select :calculator_type, @calculators, :to_s, :description, {}, {:class => 'type-select'} %>
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
  &nbsp; <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
- <%= action_form.fields_for :calculator, promotion_action.calculator do |calculator_form| %>
14
- <%= preference_fields(promotion_action.calculator, calculator_form) %>
15
- <% end %>
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
- <%= action_form.hidden_field :line_items_string %>
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
  &nbsp;<br />
39
40
  <button class="add small"> <%= t(:add) %></button>
40
41
  </div>
41
-
42
42
  </fieldset>
43
43
  </div>
@@ -19,6 +19,8 @@ en:
19
19
  spree:
20
20
  checkout:
21
21
  coupon_code_added: Coupon code added
22
+ content:
23
+ visited: Visit static content page
22
24
  expiry: Expiry
23
25
  free_shipping: Free Shipping
24
26
  new_promotion: New Promotion
@@ -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
@@ -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.rc2
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-14 00:00:00.000000000Z
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: &70362724534240 !ruby/object:Gem::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.rc2
21
+ version: 1.0.0.rc3
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70362724534240
24
+ version_requirements: *70260369514180
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: spree_auth
27
- requirement: &70362724533380 !ruby/object:Gem::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.rc2
32
+ version: 1.0.0.rc3
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70362724533380
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/20111013155037_namespace_promo_tables.rb
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,6 +0,0 @@
1
- <p class="field">
2
- <label for="<%= "#{param_prefix}_preferred_amount" %>">
3
- <%= t(:amount) %>
4
- <%= action_form.text_field :preferred_amount, :size => 10 %>
5
- </label>
6
- </p>
@@ -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