-
-
Save shopifypartners/46cbf42bd0c0b25ec69111fadf698457 to your computer and use it in GitHub Desktop.
Shopify Scripts Buy Set, get X% off script - https://www.shopify.com/partners/blog/109804486-getting-started-with-shopify-scripts-a-practical-walkthrough
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
################################################################################ | |
# Buy set, get X% off discount script. | |
# | |
# This script allows the running of a campaign to give customers X% off a "set" | |
# of items, if and only if they purchase at least one of each item in the set. | |
# | |
# The discount is applied only to all items in the set in the cart. | |
# | |
# Written by Gavin Ballard ([email protected]) | |
################################################################################ | |
################################################################################ | |
# START CUSTOMISATION SECTION | |
# | |
# You can customise the variables here at the top of the script to adjust the | |
# products the campaign applies and the message customers will see in their cart | |
# and at checkout. | |
################################################################################ | |
# Defines a list of the products that are in the set. Customers will need to | |
# purchase at least one of each product with this tag to be eligible for the | |
# discount. Setting this as an empty list (`[]`) will effectively turn off this | |
# campaign. | |
PRODUCTS_IN_SET = [] | |
# Set the percentage discount that should be applied if the customer has all | |
# products in the set in their cart. Will *only* apply to the products in the | |
# set themselves - other items in the cart won't be affected. | |
DISCOUNT_PERCENT = 10 | |
# Set the message that will be displayed to customers in their cart and at | |
# checkout to let them know their discount has been applied. | |
DISCOUNT_MESSAGE = "#{DISCOUNT_PERCENT}% off for purchasing the set!" | |
################################################################################ | |
# END CUSTOMISATION SECTION | |
# | |
# You shouldn't need to edit anything below this line, unless you're a developer | |
# and know what you're doing :). | |
################################################################################ | |
# The campaign class. | |
class BuySetGetXOffCampaign | |
def initialize(selector, discount, partitioner) | |
@selector = selector | |
@discount = discount | |
@partitioner = partitioner | |
end | |
def run(cart) | |
applicable_items = cart.line_items.select do |line_item| | |
@selector.match?(line_item) | |
end | |
discounted_items = @partitioner.partition(cart, applicable_items) | |
discounted_items.each do |line_item| | |
@discount.apply(line_item) | |
end | |
end | |
end | |
# Select line items by product id. | |
class ProductsSelector | |
def initialize(product_ids) | |
@product_ids = Array(product_ids) | |
end | |
def match?(line_item) | |
@product_ids.include?(line_item.variant.product.id) | |
end | |
end | |
# Apply a percentage discount to a line item. | |
class PercentageDiscount | |
def initialize(percent, message) | |
@percent = Decimal.new(percent) / 100.0 | |
@message = message | |
end | |
def apply(line_item) | |
line_discount = line_item.line_price * @percent | |
new_line_price = line_item.line_price - line_discount | |
line_item.change_line_price(new_line_price, message: @message) | |
puts "Discounted line item with variant #{line_item.variant.id} by #{line_discount}." | |
end | |
end | |
class ProductSetPartitioner | |
def initialize(set_product_ids) | |
@set_product_ids = set_product_ids | |
end | |
def partition(cart, applicable_line_items) | |
# If all items in the product set are in the cart, then all applicable line | |
# items are eligible for the discount. Otherwise, none of them are. | |
cart_product_ids = cart.line_items.map { |line_item| line_item.variant.product.id }.uniq | |
if (@set_product_ids - cart_product_ids).empty? | |
applicable_line_items | |
else | |
[] | |
end | |
end | |
end | |
# List of campaigns. | |
CAMPAIGNS = [ | |
BuySetGetXOffCampaign.new( | |
ProductsSelector.new(PRODUCTS_IN_SET), | |
PercentageDiscount.new(DISCOUNT_PERCENT, DISCOUNT_MESSAGE), | |
ProductSetPartitioner.new(PRODUCTS_IN_SET) | |
) | |
] | |
# Apply all defined campaiagns to the cart. | |
CAMPAIGNS.each do |campaign| | |
campaign.run(Input.cart) | |
end | |
# Export changes. | |
Output.cart = Input.cart |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment