Apply discount to most expensive item in cart

Tourist
27 0 2

I've worked through the logic of

a) create a placeholder discount code to be added and later searched for in cart

b) if discount code is present loop through line items and find highest priced item

c) change price of most expensive item by * 0.8

I built an array of hashes containing price and ID pairs, but I'm not sure where to go from here.  I am also concerned that I am not utilizing the API to its fullest, or most efficiently, and would love to know how to better use the .variant method to avoid creating the array of hashes.

Code below is missing the find discount in cart method, but that is working just fine and not the issue at hand.

#apply discount to most expensive item only once

line_item_array = []

Input.cart.line_items.each do |price_per_item|
  value = {"id"=>price_per_item.variant.id , "price"=>price_per_item.variant.price}
  line_item_array << value
end

highest_product = line_item_array.max_by{|a| a["price"]}

highest_product.change_price(highest_product.price *0.8, message: "discount")

 

0 Likes
Explorer
296 0 24

Why make an array..? Can't you just use bubble sort in .each loop to get the highest priced variant?

I make apps and can help you in setting up payment gateways..
0 Likes
Tourist
27 0 2

Did a quick review of bubble sort and I'm a bit confused...seems like you are still building an array then taking the first index to do price change.  Mind elaborating on your recommended use?

Yes, it might be a better method to use .sort, but my confusion is in how to set a variable to this high priced variant and then perform change price method for output on that variable.

0 Likes
Explorer
296 0 24

You don't need to build the array, you already have the line_items array.. Load the first element into the variable and then start comparing other items sequentially. If a new item has a higher price than that loaded variable, replace loaded variable with this new item. After the first iteration, the loaded variable will the highest priced item.

I make apps and can help you in setting up payment gateways..
0 Likes
Tourist
27 0 2

Okay, then I guess the last thing I'm not understanding is how to retrieve the ID of the highest priced item at that point.  There needs to be a hash of the ID and price pair as I understand it...what method would I call to retrieve that?

I might be out of my league at this point in terms of time I have to invest in this project before finding an expert

0 Likes
Explorer
296 0 24

I maybe wrong, but it think this is the problem..

highest_product = line_item_array.max_by{|a| a["price"]}

By the above statement, you're creating a clone of the maximum priced amount and then you are applying the price change on this clone. So the actual item is not affected.

Probably see the example on this page - https://help.shopify.com/api/tutorials/shopify-scripts

After making the changes, you may look at modifying the cart all together.

 

I make apps and can help you in setting up payment gateways..
0 Likes
Highlighted
Tourist
27 0 2

Can you be more specific with the example you are referencing in that link?

Yes the clone conclusion makes sense, but I don't know how to sort the line_items array by price only.  Usually you could target the hash item (:price), but that's not immediately evident to me.

By the way here is the bubble sort code: a bit hacked together at the end but it works.  Within scripts panel it reports a 1% CPU and 7% Memory usage.  This same method also works with the max_by code as well...just setting the max price value as the condition for the if statement.

#apply discount to most expensive item only once
def high_price(array)
  n = array.length
  
  loop do
    swapped = false
  
    (n-1).times do |i|
      if array[i] > array[i + 1]
        array[i], array[i + 1] = array[i + 1], array[i]
        swapped = true
      end
    end
    
    break if not swapped
  end 
  
  array
end
a = []
Input.cart.line_items.each do |price_per|
  a << price_per.variant.price
end
most_expensive = high_price(a).last
Input.cart.line_items.each do |find_product|
  if find_product.variant.price == most_expensive
    find_product.change_line_price(Money.zero , message:"Free Item")
  end
end
Output.cart = Input.cart

 

0 Likes
Explorer
296 0 24

Your first loop will give you the index of the highest priced item.. Take that index (check "List") in the link provided, update your line_items in Input.cart and then output it.. It should do the work..

The logic for getting the index can be something like this..

  1. Load 0 as index
  2. Load line_items[0] as highest value product
  3. From 0 to n-1 (say i), check line_items[i] price if > than highest value product price. If yes, replace highest value product by line_items[i] and load "i" as index
  4. Once loop done, update line_items[index] price according to rule

 

 

I make apps and can help you in setting up payment gateways..
0 Likes
Tourist
27 0 2

I'm trying to parse your logic, but as someone who is brand new to this, I'm not certain about the meaning behind point 1, or 2.  

If you point to line_items[0] it returns a string ID for the line_item, and when I try to view the price of that line item ID, I get the error undefined method for nul.  Can you show me an example that I might be able to pull apart as opposed to just logic discussion?

0 Likes
Explorer
296 0 24
high = Input.cart.line_items[0]

Input.cart.line_items.each do |line_item|
  if high.variant.price < line_item.variant.price
     high = line_item
  end
end

Input.cart.line_items.each do |line_item|
  if high == line_item
    line_item.change_line_price(high.variant.price * 0.80, message: "discount")
  end
end

Output.cart = Input.cart

 

I make apps and can help you in setting up payment gateways..
1 Like