spree_promo 1.1.1 → 1.1.2.rc1

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.
@@ -40,19 +40,15 @@ var initProductActions = function(){
40
40
 
41
41
  // Remove line item
42
42
  var setupRemoveLineItems = function(){
43
- $(".promotion_action.create_line_items table img").unbind('click').click(function(){
44
- var $container = $(this).parents('.promotion_action');
45
- var $hiddenField = $container.find("input[type='hidden']");
46
- var $row = $(this).parents('tr');
47
- var index = $row.parents('table').find('tr').index($row.get(0));
48
- // Remove variant_id quantity pair from the string
49
- var items = _($hiddenField.val().split(',')).compact();
50
- items.splice(index - 1, 1);
51
- $hiddenField.val(items.join(','));
43
+ $(".remove_promotion_line_item").click(function(){
44
+ line_items_el = $($('.line_items_string')[0])
45
+ finder = RegExp($(this).data("variant-id") + "x\\d+")
46
+ line_items_el.val(line_items_el.val().replace(finder, ""))
52
47
  $(this).parents('tr').remove();
53
48
  hideOrShowItemTables();
54
49
  });
55
50
  };
51
+
56
52
  setupRemoveLineItems();
57
53
  // Add line item to list
58
54
  $(".promotion_action.create_line_items button.add").unbind('click').click(function(e){
@@ -18,7 +18,12 @@ Spree::Order.class_eval do
18
18
  update_adjustments_without_promotion_limiting
19
19
  return if adjustments.promotion.eligible.none?
20
20
  most_valuable_adjustment = adjustments.promotion.eligible.max{|a,b| a.amount.abs <=> b.amount.abs}
21
- ( adjustments.promotion.eligible - [most_valuable_adjustment] ).each{|adjustment| adjustment.update_attribute_without_callbacks(:eligible, false)}
21
+ current_adjustments = (adjustments.promotion.eligible - [most_valuable_adjustment])
22
+ current_adjustments.each do |adjustment|
23
+ if adjustment.originator.calculator.is_a?(Spree::Calculator::PerItem)
24
+ adjustment.update_attribute_without_callbacks(:eligible, false)
25
+ end
26
+ end
22
27
  end
23
28
  alias_method_chain :update_adjustments, :promotion_limiting
24
29
  end
@@ -1,43 +1,48 @@
1
1
  module Spree
2
- class Promotion::Actions::CreateAdjustment < PromotionAction
3
- calculated_adjustments
2
+ class Promotion
3
+ module Actions
4
+ class CreateAdjustment < PromotionAction
5
+ calculated_adjustments
4
6
 
5
- delegate :eligible?, :to => :promotion
7
+ delegate :eligible?, :to => :promotion
6
8
 
7
- before_validation :ensure_action_has_calculator
9
+ before_validation :ensure_action_has_calculator
8
10
 
9
- def perform(options = {})
10
- return unless order = options[:order]
11
- # Nothing to do if the promotion is already associated with the order
12
- return if order.promotion_credit_exists?(promotion)
11
+ def perform(options = {})
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)
13
15
 
14
- order.adjustments.promotion.reload.clear
15
- order.update!
16
- create_adjustment("#{I18n.t(:promotion)} (#{promotion.name})", order, order)
17
- end
16
+ order.adjustments.promotion.reload.clear
17
+ order.update!
18
+ create_adjustment("#{I18n.t(:promotion)} (#{promotion.name})", order, order)
19
+ order.update!
20
+ end
18
21
 
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
- params = { :amount => amount,
25
- :source => calculable,
26
- :originator => self,
27
- :label => label,
28
- :mandatory => mandatory }
29
- target.adjustments.create(params, :without_protection => true)
30
- end
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
25
+ def create_adjustment(label, target, calculable, mandatory=false)
26
+ amount = compute_amount(calculable)
27
+ params = { :amount => amount,
28
+ :source => calculable,
29
+ :originator => self,
30
+ :label => label,
31
+ :mandatory => mandatory }
32
+ target.adjustments.create(params, :without_protection => true)
33
+ end
31
34
 
32
- # Ensure a negative amount which does not exceed the sum of the order's item_total and ship_total
33
- def compute_amount(calculable)
34
- [(calculable.item_total + calculable.ship_total), super.to_f.abs].min * -1
35
- end
35
+ # Ensure a negative amount which does not exceed the sum of the order's item_total and ship_total
36
+ def compute_amount(calculable)
37
+ [(calculable.item_total + calculable.ship_total), super.to_f.abs].min * -1
38
+ end
36
39
 
37
- private
38
- def ensure_action_has_calculator
39
- return if self.calculator
40
- self.calculator = Calculator::FlatPercentItemTotal.new
40
+ private
41
+ def ensure_action_has_calculator
42
+ return if self.calculator
43
+ self.calculator = Calculator::FlatPercentItemTotal.new
44
+ end
45
+ end
41
46
  end
42
47
  end
43
- end
48
+ end
@@ -1,31 +1,36 @@
1
1
  module Spree
2
- class Promotion::Actions::CreateLineItems < PromotionAction
3
- has_many :promotion_action_line_items, :foreign_key => 'promotion_action_id'
2
+ class Promotion
3
+ module Actions
4
+ class CreateLineItems < PromotionAction
5
+ has_many :promotion_action_line_items, :foreign_key => 'promotion_action_id'
4
6
 
5
- attr_accessor :line_items_string
7
+ attr_accessor :line_items_string
6
8
 
7
- def perform(options = {})
8
- return unless order = options[:order]
9
- promotion_action_line_items.each do |item|
10
- current_quantity = order.quantity_of(item.variant)
11
- if current_quantity < item.quantity
12
- order.add_variant(item.variant, item.quantity - current_quantity)
9
+ def perform(options = {})
10
+ return unless order = options[:order]
11
+ promotion_action_line_items.each do |item|
12
+ current_quantity = order.quantity_of(item.variant)
13
+ if current_quantity < item.quantity
14
+ order.add_variant(item.variant, item.quantity - current_quantity)
15
+ order.update!
16
+ end
17
+ end
13
18
  end
14
- end
15
- end
16
19
 
17
- def line_items_string
18
- promotion_action_line_items.map { |li| "#{li.variant_id}x#{li.quantity}" }.join(',')
19
- end
20
+ def line_items_string
21
+ promotion_action_line_items.map { |li| "#{li.variant_id}x#{li.quantity}" }.join(',')
22
+ end
20
23
 
21
- def line_items_string=(value)
22
- promotion_action_line_items.destroy_all
23
- value.to_s.split(',').each do |str|
24
- variant_id, quantity = str.split('x')
25
- if variant_id && quantity && variant = Variant.find_by_id(variant_id)
26
- promotion_action_line_items.create({:variant => variant, :quantity => quantity.to_i}, :without_protection => true)
24
+ def line_items_string=(value)
25
+ promotion_action_line_items.destroy_all
26
+ value.to_s.split(',').each do |str|
27
+ variant_id, quantity = str.split('x')
28
+ if variant_id && quantity && variant = Variant.find_by_id(variant_id)
29
+ promotion_action_line_items.create({:variant => variant, :quantity => quantity.to_i}, :without_protection => true)
30
+ end
31
+ end
27
32
  end
28
33
  end
29
34
  end
30
35
  end
31
- end
36
+ end
@@ -1,8 +1,12 @@
1
1
  module Spree
2
- class Promotion::Rules::FirstOrder < PromotionRule
3
- def eligible?(order, options = {})
4
- user = order.try(:user) || options[:user]
5
- !!(user && user.orders.complete.count == 0)
2
+ class Promotion
3
+ module Rules
4
+ class FirstOrder < PromotionRule
5
+ def eligible?(order, options = {})
6
+ user = order.try(:user) || options[:user]
7
+ !!(user && user.orders.complete.count == 0)
8
+ end
9
+ end
6
10
  end
7
11
  end
8
12
  end
@@ -1,16 +1,20 @@
1
1
  # A rule to limit a promotion to a specific user.
2
2
  module Spree
3
- class Promotion::Rules::ItemTotal < PromotionRule
4
- preference :amount, :decimal, :default => 100.00
5
- preference :operator, :string, :default => '>'
3
+ class Promotion
4
+ module Rules
5
+ class ItemTotal < PromotionRule
6
+ preference :amount, :decimal, :default => 100.00
7
+ preference :operator, :string, :default => '>'
6
8
 
7
- attr_accessible :preferred_amount, :preferred_operator
9
+ attr_accessible :preferred_amount, :preferred_operator
8
10
 
9
- OPERATORS = ['gt', 'gte']
11
+ OPERATORS = ['gt', 'gte']
10
12
 
11
- def eligible?(order, options = {})
12
- item_total = order.line_items.map(&:amount).sum
13
- item_total.send(preferred_operator == 'gte' ? :>= : :>, BigDecimal.new(preferred_amount.to_s))
13
+ def eligible?(order, options = {})
14
+ item_total = order.line_items.map(&:amount).sum
15
+ item_total.send(preferred_operator == 'gte' ? :>= : :>, BigDecimal.new(preferred_amount.to_s))
16
+ end
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -2,32 +2,45 @@
2
2
  # Can require all or any of the products to be present.
3
3
  # Valid products either come from assigned product group or are assingned directly to the rule.
4
4
  module Spree
5
- class Promotion::Rules::Product < PromotionRule
6
- has_and_belongs_to_many :products, :class_name => '::Spree::Product', :join_table => 'spree_products_promotion_rules', :foreign_key => 'promotion_rule_id'
5
+ class Promotion
6
+ module Rules
7
+ class Product < PromotionRule
8
+ has_and_belongs_to_many :products, :class_name => '::Spree::Product', :join_table => 'spree_products_promotion_rules', :foreign_key => 'promotion_rule_id'
9
+ validate :only_one_promotion_per_product
7
10
 
8
- MATCH_POLICIES = %w(any all)
9
- preference :match_policy, :string, :default => MATCH_POLICIES.first
11
+ MATCH_POLICIES = %w(any all)
12
+ preference :match_policy, :string, :default => MATCH_POLICIES.first
10
13
 
11
- # scope/association that is used to test eligibility
12
- def eligible_products
13
- products
14
- end
14
+ # scope/association that is used to test eligibility
15
+ def eligible_products
16
+ products
17
+ end
15
18
 
16
- def eligible?(order, options = {})
17
- return true if eligible_products.empty?
18
- if preferred_match_policy == 'all'
19
- eligible_products.all? {|p| order.products.include?(p) }
20
- else
21
- order.products.any? {|p| eligible_products.include?(p) }
22
- end
23
- end
19
+ def eligible?(order, options = {})
20
+ return true if eligible_products.empty?
21
+ if preferred_match_policy == 'all'
22
+ eligible_products.all? {|p| order.products.include?(p) }
23
+ else
24
+ order.products.any? {|p| eligible_products.include?(p) }
25
+ end
26
+ end
24
27
 
25
- def product_ids_string
26
- product_ids.join(',')
27
- end
28
+ def product_ids_string
29
+ product_ids.join(',')
30
+ end
28
31
 
29
- def product_ids_string=(s)
30
- self.product_ids = s.to_s.split(',').map(&:strip)
32
+ def product_ids_string=(s)
33
+ self.product_ids = s.to_s.split(',').map(&:strip)
34
+ end
35
+
36
+ private
37
+
38
+ def only_one_promotion_per_product
39
+ if Spree::Promotion::Rules::Product.all.map(&:products).flatten.uniq!
40
+ errors[:base] << "You can't create two promotions for the same product"
41
+ end
42
+ end
43
+ end
31
44
  end
32
45
  end
33
46
  end
@@ -1,18 +1,24 @@
1
1
  module Spree
2
- class Promotion::Rules::User < PromotionRule
3
- belongs_to :user
4
- has_and_belongs_to_many :users, :class_name => '::Spree::User', :join_table => 'spree_promotion_rules_users', :foreign_key => 'promotion_rule_id'
2
+ class Promotion
3
+ module Rules
4
+ class User < PromotionRule
5
+ attr_accessible :user_ids_string
5
6
 
6
- def eligible?(order, options = {})
7
- users.none? or users.include?(order.user)
8
- end
7
+ belongs_to :user, :class_name => "Spree::User"
8
+ has_and_belongs_to_many :users, :class_name => '::Spree::User', :join_table => 'spree_promotion_rules_users', :foreign_key => 'promotion_rule_id'
9
9
 
10
- def user_ids_string
11
- user_ids.join(',')
12
- end
10
+ def eligible?(order, options = {})
11
+ users.none? or users.include?(order.user)
12
+ end
13
+
14
+ def user_ids_string
15
+ user_ids.join(',')
16
+ end
13
17
 
14
- def user_ids_string=(s)
15
- self.user_ids = s.to_s.split(',').map(&:strip)
18
+ def user_ids_string=(s)
19
+ self.user_ids = s.to_s.split(',').map(&:strip)
20
+ end
21
+ end
16
22
  end
17
23
  end
18
24
  end
@@ -1,15 +1,20 @@
1
1
  module Spree
2
- class Promotion::Rules::UserLoggedIn < PromotionRule
3
- def eligible?(order, options = {})
2
+ class Promotion
3
+ module Rules
4
+ class UserLoggedIn < PromotionRule
4
5
 
5
- # this is tricky. We couldn't use any of the devise methods since we aren't in the controller.
6
- # we need to rely on the controller already having done this for us.
6
+ def eligible?(order, options = {})
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.
7
9
 
8
- # The thinking is that the controller should have some sense of what state
9
- # we should be in before firing events,
10
- # so the controller will have to set this field.
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.
11
13
 
12
- return options && options[:user_signed_in]
14
+ return options && options[:user_signed_in]
15
+ end
16
+
17
+ end
13
18
  end
14
19
  end
15
20
  end
@@ -14,6 +14,8 @@ module Spree
14
14
  alias_method :actions, :promotion_actions
15
15
  accepts_nested_attributes_for :promotion_actions
16
16
 
17
+ validates_associated :rules
18
+
17
19
  attr_accessible :name, :event_name, :code, :match_policy,
18
20
  :path, :advertise, :description, :usage_limit,
19
21
  :starts_at, :expires_at, :promotion_rules_attributes,
@@ -2,10 +2,12 @@
2
2
  # PromotionActions perform the necessary tasks when a promotion is activated by an event and determined to be eligible.
3
3
  module Spree
4
4
  class PromotionAction < ActiveRecord::Base
5
- belongs_to :promotion, :foreign_key => 'activator_id'
5
+ belongs_to :promotion, :foreign_key => 'activator_id', :class_name => "Spree::Promotion"
6
6
 
7
7
  scope :of_type, lambda {|t| {:conditions => {:type => t}}}
8
8
 
9
+ attr_accessible :line_items_string
10
+
9
11
  # This method should be overriden in subclass
10
12
  # Updates the state of the order or performs some other action depending on the subclass
11
13
  # options will contain the payload from the event that activated the promotion. This will include
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class PromotionActionLineItem < ActiveRecord::Base
3
3
  belongs_to :promotion_action, :class_name => 'Spree::Promotion::Actions::CreateLineItems'
4
- belongs_to :variant
4
+ belongs_to :variant, :class_name => "Spree::Variant"
5
5
  end
6
6
  end
@@ -1,7 +1,7 @@
1
1
  # Base class for all promotion rules
2
2
  module Spree
3
3
  class PromotionRule < ActiveRecord::Base
4
- belongs_to :promotion, :foreign_key => 'activator_id'
4
+ belongs_to :promotion, :foreign_key => 'activator_id', :class_name => "Spree::Promotion"
5
5
 
6
6
  scope :of_type, lambda {|t| {:conditions => {:type => t}}}
7
7
 
@@ -13,7 +13,7 @@
13
13
  <%= item.quantity %>
14
14
  </td>
15
15
  <td>
16
- <%= image_tag 'admin/icons/cross.png' %>
16
+ <%= image_tag 'admin/icons/cross.png', :class => "remove_promotion_line_item", :data => { :variant_id => item.variant_id } %>
17
17
  </td>
18
18
  </tr>
19
19
  <% end %>
metadata CHANGED
@@ -1,38 +1,38 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_promo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
5
- prerelease:
4
+ version: 1.1.2.rc1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - David North
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-16 00:00:00.000000000 Z
12
+ date: 2012-06-25 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: spree_core
16
- requirement: &70340061938220 !ruby/object:Gem::Requirement
16
+ requirement: &70249530014760 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - =
20
20
  - !ruby/object:Gem::Version
21
- version: 1.1.1
21
+ version: 1.1.2.rc1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70340061938220
24
+ version_requirements: *70249530014760
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: spree_auth
27
- requirement: &70340061937140 !ruby/object:Gem::Requirement
27
+ requirement: &70249530003060 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - =
31
31
  - !ruby/object:Gem::Version
32
- version: 1.1.1
32
+ version: 1.1.2.rc1
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70340061937140
35
+ version_requirements: *70249530003060
36
36
  description: Required dependency for Spree
37
37
  email: david@spreecommerce.com
38
38
  executables: []
@@ -127,12 +127,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
127
  required_rubygems_version: !ruby/object:Gem::Requirement
128
128
  none: false
129
129
  requirements:
130
- - - ! '>='
130
+ - - ! '>'
131
131
  - !ruby/object:Gem::Version
132
- version: '0'
133
- segments:
134
- - 0
135
- hash: -2121439115021991443
132
+ version: 1.3.1
136
133
  requirements:
137
134
  - none
138
135
  rubyforge_project: