Buy 3 get 1 free, except for discounted products - script breaks after 4 items have been added

Griffing325
Tourist
5 1 0

Hey, so on our website we have a "buy 3 get 1 free" type of deal, and we're about to a clearance page. The items on the clearance page shouldn't count towards our buy 3 get 1 free deal.

 

The script first checks to see if the item is an item at full price. (8.99 or 9.99). If it is not, then it's a discounted variant (select few variants per product will be discounted to 6.29) and is skipped by the script all together.  If it is a matching full priced item, I check to see if it has a type attribute (we only use this attribute for gifts, so that's why we haven't added a check for the type "gift" directly) then I set the variable for how many gifts are in the cart based on that. If it does not contain the gift type, then I increment the total products, excluding gifts or anything that doesn't have the product tag, to get the allowed gifts value. I then use that value to loop over the cart and apply the discount to any allowed gifts, once the allowed limit as passed then the prices should remain unaffected in case a customer managed to get an unearned gift item in the cart.

 

So the issue I am having with this script is it doesn't work after the first gift is earned.  Once a customer has 3 full priced items in the cart, the 4th free gift is set to free, but the moment I add 4 full priced items the gift is back at full price. It only works correctly exactly at 3 items, and 1 free gift. When a customer has 4 or 5 full priced items, the gift should remain free, and at 6 full items 2 gifts should be free.

I should also note, this script worked fine before I added the check for the discounted items, but I haven't changed the way the math logic works so I do not understand why it's not working as desired.

 

$totalCart = 0
$totalGifts = 0
$allowedGifts = 0
$i = 1
Input.cart.line_items.each do |line_item|
  product = line_item.variant.product
  if line_item.variant.price == Money.new(cents: 899) || line_item.variant.price == Money.new(cents: 999)
    if product.tags.include? 'product'
      if line_item.properties.has_key?("type")
        while line_item.quantity > 1
          line_item.split(take:1)
        end
        $totalGifts = $totalGifts + line_item.quantity
        puts $totalGifts
      else
        $totalCart = $totalCart + line_item.quantity
        puts $totalCart
      end
    end
  end
end
$allowedGifts = $totalCart / 3
puts $allowedGifts.floor()
Input.cart.line_items.each do |line_item|
   if line_item.variant.price == Money.new(cents: 899) || line_item.variant.price == Money.new(cents: 999)
    if line_item.properties.has_key?("type")
      if $allowedGifts.floor() >= $i
        $i = $i + 1
        puts "got here"
        line_item.change_line_price(line_item.line_price * 0.0, message: line_item.properties["type"])
      else
        line_item.change_line_price(line_item.line_price * 1.0, message: "Free gift conditions not met!")
      end
    end
  end
end
Output.cart = Input.cart

 

I appreciate any help anyone has to give regarding this. Thank you!

 

P.S. My only experience with ruby is shopify script editor, I am a novice in this language no doubt.

Replies 2 (2)

Griffing325
Tourist
5 1 0

I tried rewriting the script to see if I could fix it, but this script handles the same as the prior script I posted. 

 

I have figured out that the script is messing up once an item has more than 1 qty. For example, if I buy 1 product A, 1 product b, and 1 product c, I'm offered that 4th gift for free.  If I have 6 unique products, at 1 quantity each the script does allow the 2nd gift to be free as well, but it's whenever there's more than 1 quantity on a paid for product that the script messes up.

 

 

$totalCart = 0
$totalGifts = 0
$allowedGifts = 0

def isProduct?(line_item)
  if  line_item.variant.product.tags.include? 'product'
    product = true
  else
    product = false
  end
  return product
end

def isGift?(line_item)
  if  line_item.variant.product.tags.include? 'product' and line_item.properties.has_key?("type")
    product = true
  else
    product = false
  end
  return product
end

def isDiscounted?(line_item)
  if line_item.variant.price == Money.new(cents: 899) || line_item.variant.price == Money.new(cents: 999) || line_item.variant.price == Money.new(cents: 1199) || line_item.variant.price == Money.new(cents: 1299)
   return false
  else
   return true
  end
end

Input.cart.line_items.each do |line_item|
  if isDiscounted?(line_item)
    #do nothing
  else
    if isProduct?(line_item)
      if isGift?(line_item)
      #is a product, and is a gift. 
        while line_item.quantity > 1
          line_item.split(take:1)
        end
      $totalGifts = $totalGifts + line_item.quantity
      else
      #not a gift, but is a product. 
      $totalCart = $totalCart + line_item.quantity
      end
    end
  end
if ($totalCart / 3).floor >= $totalGifts && isGift?(line_item)
  line_item.change_line_price(line_item.line_price * 0.0, message: line_item.properties["type"])
end
end

Output.cart = Input.cart

 

 

Again, I appreciate any guidance on this whatsoever. Thanks!

playwright-mike
Shopify Partner
72 18 33

Hi @Griffing325,

I tried to look at your script, but realized that this one can get a bit complicated. So instead, I used an app am developing called Playwright. While we don't support this exact feature, I was able to make a few adjustments to support your use case.

You can view the script here: http://kaliara.com/shopify-script.rb (it was too large to paste into this post).

 

Here is a demo of it working for me. Including the following features:

  • lowest priced item is the one discounted
  • non-eligible item doesn't count (this one is missing the 'product' tag)
  • mine shows real-time cart updates, but this is mostly for checkout

Note: keep in mind that you probably cannot test this in the Script Editor debug tool because of the use of line_item.properties)

 

Let me know if that works for you!

Matthew

 

Playwright | Create Shopify Scripts without writing code | https://playwrightapp.com
- Was my reply helpful? Please Like and Accept Solution.