We're trying to use Shopify Scripts to prevent discount codes from being applied to items that are already on sale (i.e. have a Discount code that applies to them), so that customers can't get a double sale. When we put an item on sale we update the variant price to the sale price, and set the original price in the "compare_at_price". Additionally, it is tagged as "On Sale". So I thought I could make a script like so:
Input.cart.line_items.each do |line_item| product = line_item.variant.product next unless product.tags.include?('On Sale') and line_item.line_price_changed? line_item.change_line_price(line_item.line_price_was, message: "Discount does not apply to sale items") end Output.cart = Input.cart
A link to the actual script:
We published and put a relevant item in the cart but nothing happened. We realized that the issue probably has to do with the fact that a percentage discount applies to the whole subtotal, not the line item, so our script doesn't do anything because the line_price is the same as the line_was_price.
The new problem is that according to the docs there's no way to change the subtotal in order to undo the discount for the items that are "on sale". So ideally I could do something like the following, which obviously won't actually work. Can anyone make any suggestions for alternative approaches to the same effect?
unless Input.cart.subtotal_price_changed? and Input.cart.discount_code == CartDiscount::Percentage exit end discount_percentage = Input.cart.discount_code.percentage amount_to_recover = 0 Input.cart.line_items.each do |line_item| product = line_item.variant.product next unless product.tags.include?('On Sale') amount_to_recover = amount_to_recover + (line_item.line_price * discount_percentage) end Input.cart.change_subtotal_price(Input.cart.subtotal_price + amount_to_recover, message: 'Discounts do not apply to sale items.') Output.cart = Input.cart
Thank you for reading and looking into this, for us!
TL; DR: We are working on better ways for the Scripts to interact with discount codes. For now, the only way I can see is to use Scripts to apply the sale, so that you can choose which items to apply it to.
There's a few things to unwind here. Your approach is completely sane but you're hitting the limits of the features we currently offer.
First, let's discuss your last approach, taking the `amount_to_recover`. Scripts currently only allow giving discounts. In fact, if you try to run the following code to add 1$ to any prices, you'll see an error:
line_item = Input.cart.line_items.first line_item.change_line_price( line_item.line_price + Money.new(cents: 100), message: "test" ) #=> [Error] new line_price must be lower than the current line_price
As you see, it's currently not possible to increase the price of line items (or subtotal), so unfortunately this approach doesn't work.
The first approach, relying on `line_price_was`, has a few issues. The first and possibly most important problem is that discount codes are calculated after scripts. The reason is that scripts can have an effect on the preconditions of the discount codes.
Take the following example: you have a discount code that gives 5% off orders above 100$. You also have a script that applies 10% to everything in store. A customer comes in with a cart totaling 100$. The script runs, and the cart is now 90$. When the discount code is calculated, it is not applied because the preconditions are not met.
With that knowledge you'll realize that you were close in understanding that the `line_price_was` wasn't changed, simply not for the right reason.
We are currently working on ways for the scripts to better interact with discount codes. You would be able to disable the code winthin the script if an item is on sale, for example.
Hope that helps,
We've just added the ability to reject discount codes from Scripts. The usage details can be found in the API reference under the CartDiscount objects, specifically the reject and rejected? methods.
Furthermore, you can now test the interaction between your script and discount codes from within the Script Editor.