From 90c837f6667fecb82ebc765128f1897deae633ff Mon Sep 17 00:00:00 2001 From: Josh Shupack Date: Wed, 29 Feb 2012 16:04:22 -0800 Subject: [PATCH 1/9] products with variants now related properly --- app/models/spree/calculator/related_product_discount.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/spree/calculator/related_product_discount.rb b/app/models/spree/calculator/related_product_discount.rb index 65e48707..9aa98be7 100644 --- a/app/models/spree/calculator/related_product_discount.rb +++ b/app/models/spree/calculator/related_product_discount.rb @@ -17,11 +17,11 @@ def compute(object) return unless eligible?(order) total = order.line_items.inject(0) do |total, line_item| relations = Spree::Relation.find(:all, :conditions => ["discount_amount <> 0.0 AND relatable_type = ? AND relatable_id = ?", "Spree::Product", line_item.variant.product.id]) - discount_applies_to = relations.map {|rel| rel.related_to.master } + discount_applies_to = relations.map {|rel| rel.related_to } order.line_items.each do |li| - if discount_applies_to.include? li.variant - discount = relations.detect {|rel| rel.related_to.master == li.variant}.discount_amount + if discount_applies_to.include? li.product + discount = relations.detect {|rel| rel.related_to == li.product}.discount_amount total += if li.quantity < line_item.quantity (discount * li.quantity) From 4da6f63ae269622bc9c6c155dd9eefecdb845a9c Mon Sep 17 00:00:00 2001 From: Josh Shupack Date: Wed, 29 Feb 2012 16:47:50 -0800 Subject: [PATCH 2/9] updated readme for new promotion system --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 27638597..1cf8ba7a 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,9 @@ You can access all related products regardless of RelationType by: Discounts You can optionally specify a discount amount to be applied if a customer purchases both products. -Note: In order for the coupon to be automatically applied, you must create a promotion leaving the __code__ value empty, and adding an Action of type : __RelatedProductDiscount__ (blank codes are required for coupons to be automatically applied). +Note: In order for the coupon to be automatically applied, you must create a promotion and add a "Create adjustment" action with a __Related Product Discount__ calculator. You should be able to add any other criteria or actions that you want as well. If you don't add any rules, it should be applied to all orders w/ matching products. + +Note: Item Total Threshold is NOT implemented Installation ------------ From a8a99fbcd859e51ac9d0e721ee39ec338cfd4357 Mon Sep 17 00:00:00 2001 From: Josh Shupack Date: Wed, 29 Feb 2012 17:34:59 -0800 Subject: [PATCH 3/9] change discount to percentage of matched product --- .../spree/calculator/related_product_discount.rb | 12 +++++------- app/models/spree/relation.rb | 1 + .../admin/products/_related_products_table.html.erb | 4 ++-- config/locales/en.yml | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/app/models/spree/calculator/related_product_discount.rb b/app/models/spree/calculator/related_product_discount.rb index 9aa98be7..22db324b 100644 --- a/app/models/spree/calculator/related_product_discount.rb +++ b/app/models/spree/calculator/related_product_discount.rb @@ -21,13 +21,11 @@ def compute(object) order.line_items.each do |li| if discount_applies_to.include? li.product - discount = relations.detect {|rel| rel.related_to == li.product}.discount_amount - - total += if li.quantity < line_item.quantity - (discount * li.quantity) - else - (discount * line_item.quantity) - end + discount_percent = relations.detect {|rel| rel.related_to == li.product}.discount_amount + + # only apply the discount as many times as the minimum quantity of matching products + quantity = [li.quantity, line_item.quantity].min + total += (li.price * discount_percent / 100.0) * quantity end end diff --git a/app/models/spree/relation.rb b/app/models/spree/relation.rb index b90bbf49..ebe73fea 100644 --- a/app/models/spree/relation.rb +++ b/app/models/spree/relation.rb @@ -4,4 +4,5 @@ class Spree::Relation < ActiveRecord::Base belongs_to :related_to, :polymorphic => true validates_presence_of :relation_type, :relatable, :related_to + validates_inclusion_of :discount_amount, :in => 0..100 end diff --git a/app/views/spree/admin/products/_related_products_table.html.erb b/app/views/spree/admin/products/_related_products_table.html.erb index 747483ed..1e3374c9 100644 --- a/app/views/spree/admin/products/_related_products_table.html.erb +++ b/app/views/spree/admin/products/_related_products_table.html.erb @@ -10,8 +10,8 @@ <% product.relations.each do |relation| %> - <%= relation.related_to.name %> - <%= relation.discount_amount != 0 ? number_to_currency(relation.discount_amount) : "-" %> + <%= link_to relation.related_to.name, relation.related_to %> + <%= relation.discount_amount != 0 ? number_to_percentage(relation.discount_amount, :precision => 0) : "none" %> <%= relation.relation_type.name %> <%= link_to_delete relation, {:url => admin_product_relation_url(relation.relatable, relation)} %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 74d5cc15..d38736e8 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,6 +1,6 @@ en: new_relation_type: New Relation Type - discount_amount: Discount Amount + discount_amount: Discount % related_product_discount: Related Product Discount relation_types: Relation Types applies_to: Applies To From d618251b87171625d235673ec8ffd1d05ec5c39b Mon Sep 17 00:00:00 2001 From: Josh Shupack Date: Mon, 12 Mar 2012 14:00:01 -0700 Subject: [PATCH 4/9] megred conflict --- app/controllers/spree/admin/relations_controller.rb | 9 ++++++++- .../admin/products/_related_products_table.html.erb | 5 +++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/controllers/spree/admin/relations_controller.rb b/app/controllers/spree/admin/relations_controller.rb index 982e23e7..ead96d81 100644 --- a/app/controllers/spree/admin/relations_controller.rb +++ b/app/controllers/spree/admin/relations_controller.rb @@ -3,7 +3,7 @@ module Admin class RelationsController < BaseController before_filter :load_data, :only => [:create, :destroy] - respond_to :js + respond_to :js, :html def create @relation = Relation.new(params[:relation]) @@ -14,6 +14,13 @@ def create respond_with(@relation) end + def update + @relation = Relation.find(params[:id]) + @relation.update_attribute :discount_amount, params[:relation][:discount_amount] || 0 + + redirect_to( related_admin_product_url(@relation.relatable) ) + end + def destroy @relation = Relation.find(params[:id]) @relation.destroy diff --git a/app/views/spree/admin/products/_related_products_table.html.erb b/app/views/spree/admin/products/_related_products_table.html.erb index 747483ed..148c2b04 100644 --- a/app/views/spree/admin/products/_related_products_table.html.erb +++ b/app/views/spree/admin/products/_related_products_table.html.erb @@ -10,8 +10,9 @@ <% product.relations.each do |relation| %> - <%= relation.related_to.name %> - <%= relation.discount_amount != 0 ? number_to_currency(relation.discount_amount) : "-" %> + <%= link_to relation.related_to.name, relation.related_to %> + <%= form_for(relation, url:admin_product_relation_path(relation.relatable, relation)) do |f| %> + <%= f.text_field :discount_amount, :size => 4 %>   <%= f.submit 'Update' %> <% end %> <%= relation.relation_type.name %> <%= link_to_delete relation, {:url => admin_product_relation_url(relation.relatable, relation)} %> From 24812a3115f6a4d51f991d91e556e77b5c14873f Mon Sep 17 00:00:00 2001 From: Josh Shupack Date: Mon, 12 Mar 2012 14:31:42 -0700 Subject: [PATCH 5/9] updated wording --- .../spree/admin/products/_related_products_table.html.erb | 2 +- config/locales/en.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/spree/admin/products/_related_products_table.html.erb b/app/views/spree/admin/products/_related_products_table.html.erb index 148c2b04..1de92e77 100644 --- a/app/views/spree/admin/products/_related_products_table.html.erb +++ b/app/views/spree/admin/products/_related_products_table.html.erb @@ -12,7 +12,7 @@ <%= link_to relation.related_to.name, relation.related_to %> <%= form_for(relation, url:admin_product_relation_path(relation.relatable, relation)) do |f| %> - <%= f.text_field :discount_amount, :size => 4 %>   <%= f.submit 'Update' %> <% end %> + <%= f.text_field :discount_amount, :size => 4 %>%   <%= f.submit 'Update' %> <% end %> <%= relation.relation_type.name %> <%= link_to_delete relation, {:url => admin_product_relation_url(relation.relatable, relation)} %> diff --git a/config/locales/en.yml b/config/locales/en.yml index d38736e8..1eef866c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,12 +1,12 @@ en: new_relation_type: New Relation Type discount_amount: Discount % - related_product_discount: Related Product Discount + related_product_discount: Matching Product Discount relation_types: Relation Types applies_to: Applies To editing_relation_type: Editing Relation Type - related_products: Related Products - add_related_product: Add Related Product + related_products: Matching Products + add_related_product: Add Matching Product name_or_sku: Name or SKU manage_relation_types: Manage relation types no_relation_types: You need to configure Relation Types before you can use this feature. From ef67d152e9b1a6127bc25894e56bb7859a0ac3b8 Mon Sep 17 00:00:00 2001 From: Josh Shupack Date: Tue, 13 Mar 2012 23:41:27 -0700 Subject: [PATCH 6/9] added related_tos to products - bad name but could not think of anything better --- app/models/spree/product_decorator.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/spree/product_decorator.rb b/app/models/spree/product_decorator.rb index fc97d7d6..da0e9270 100644 --- a/app/models/spree/product_decorator.rb +++ b/app/models/spree/product_decorator.rb @@ -1,5 +1,6 @@ Spree::Product.class_eval do has_many :relations, :as => :relatable + has_many :related_tos, :as => :related_to, :class_name => 'Relation' # Returns all the Spree::RelationType's which apply_to this class. def self.relation_types From 22b46ca454e87d2bb657b7f16aba15bcfe345e57 Mon Sep 17 00:00:00 2001 From: Josh Shupack Date: Fri, 4 May 2012 00:37:28 -0700 Subject: [PATCH 7/9] allow spree 1.1 --- spree_related_products.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spree_related_products.gemspec b/spree_related_products.gemspec index 9f9808cb..21155a7f 100644 --- a/spree_related_products.gemspec +++ b/spree_related_products.gemspec @@ -17,8 +17,8 @@ Gem::Specification.new do |s| s.has_rdoc = true - s.add_dependency 'spree_core', '~> 1.0.0' - s.add_dependency 'spree_promo', '~> 1.0.0' + s.add_dependency 'spree_core', '>= 1.0.0' + s.add_dependency 'spree_promo', '>= 1.0.0' s.add_development_dependency 'factory_girl' s.add_development_dependency 'rspec-rails', ' ~> 2.8.0.rc1' From 42230d27cb808796097d5f8552a4650644d75aa9 Mon Sep 17 00:00:00 2001 From: Josh Shupack Date: Wed, 6 Jun 2012 23:20:52 -0700 Subject: [PATCH 8/9] updated how discount is applied. Unlimited discount as long as one matching product is in cart. --- .../calculator/related_product_discount.rb | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/app/models/spree/calculator/related_product_discount.rb b/app/models/spree/calculator/related_product_discount.rb index 22db324b..15c04beb 100644 --- a/app/models/spree/calculator/related_product_discount.rb +++ b/app/models/spree/calculator/related_product_discount.rb @@ -14,30 +14,42 @@ def compute(object) order = object end - return unless eligible?(order) - total = order.line_items.inject(0) do |total, line_item| - relations = Spree::Relation.find(:all, :conditions => ["discount_amount <> 0.0 AND relatable_type = ? AND relatable_id = ?", "Spree::Product", line_item.variant.product.id]) - discount_applies_to = relations.map {|rel| rel.related_to } - - order.line_items.each do |li| - if discount_applies_to.include? li.product - discount_percent = relations.detect {|rel| rel.related_to == li.product}.discount_amount - - # only apply the discount as many times as the minimum quantity of matching products - quantity = [li.quantity, line_item.quantity].min - total += (li.price * discount_percent / 100.0) * quantity + # related_to is the one that gets the discount + product_ids = order.line_items.map{|i| i.variant.product_id}.uniq + discounts = Spree::Relation.where(["discount_amount <> 0.0 AND related_to_type = ? AND related_to_id IN (?)", "Spree::Product", product_ids]).all.group_by(&:related_to_id) + return if discounts.empty? + + total = 0 + order.line_items.each do |line_item| + relations_for_line_item = discounts[line_item.variant.product_id] + next if relations_for_line_item.blank? + + discount_percent = 0 + relations_for_line_item.each do |relation_for_line_item| + if product_ids.include?( relation_for_line_item.relatable_id ) + # Apply the maximum available discount percentage + discount_percent = [discount_percent, + relation_for_line_item.discount_amount].max end end - - total + if line_item.respond_to?(:total_discount) + discount = line_item.total_discount + else + discount = ((line_item.price * discount_percent / 100.0) * line_item.quantity).round(2) + end + if line_item.respond_to?(:discount_percent) + line_item.update_column( :discount_percent, discount_percent ) + end + total += discount end total == 0 ? nil : total end def eligible?(order) - order.line_items.any? { |line_item| Spree::Relation.exists?(["discount_amount <> 0.0 AND relatable_type = ? AND relatable_id = ?", "Spree::Product", line_item.variant.product.id])} + product_ids = order.line_items.map{|i| i.variant.product_id}.uniq + Spree::Relation.where(["discount_amount <> 0.0 AND related_to_type = ? AND related_to_id IN (?)", "Spree::Product", product_ids]).exists? end end -end +end \ No newline at end of file From dd5fbad39edba3b4850caf52185bc3e696b91e39 Mon Sep 17 00:00:00 2001 From: Josh Shupack Date: Thu, 7 Jun 2012 15:14:39 -0700 Subject: [PATCH 9/9] bug fix for discount --- app/models/spree/calculator/related_product_discount.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/models/spree/calculator/related_product_discount.rb b/app/models/spree/calculator/related_product_discount.rb index 15c04beb..d77cc73e 100644 --- a/app/models/spree/calculator/related_product_discount.rb +++ b/app/models/spree/calculator/related_product_discount.rb @@ -32,11 +32,7 @@ def compute(object) relation_for_line_item.discount_amount].max end end - if line_item.respond_to?(:total_discount) - discount = line_item.total_discount - else - discount = ((line_item.price * discount_percent / 100.0) * line_item.quantity).round(2) - end + discount = ((line_item.price * discount_percent / 100.0) * line_item.quantity).round(2) if line_item.respond_to?(:discount_percent) line_item.update_column( :discount_percent, discount_percent ) end