Forked from shopifypartners/shopify-scripts-buy-set-get-x-off-script.rb
Last active
August 10, 2018 12:10
-
-
Save jklue/11ecafb7da59939a93cbe88dc074f5e7 to your computer and use it in GitHub Desktop.
Bundle items in the cart for a discount according to set product types
This file contains 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
################################################################################ | |
# Get discount off planner if bundle items also in cart. | |
# | |
# This script applies a discount to the planner item if a certain number of other | |
# bundled products are in the cart. | |
# | |
################################################################################ | |
################################################################################ | |
# START CUSTOMISATION SECTION | |
# | |
# You can customise the variables here at the top of the script to adjust the | |
# products in the bundle, the discount, and the message customers will see in their cart | |
# and at checkout. | |
################################################################################ | |
# Defines a list of the products that are in the bundle. 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