Need Help Combining Customer Tag and Product Tag Discount Scripts
I’m trying to merge two different discount scripts from Shopify’s documentation. The goal is to create a combined script that only gives discounts to specific products (tagged with something like “sale-item”) when the customer has a certain tag (like “premium-member”).
I’ve been struggling with this for a while and my attempts keep failing. Here’s what I tried so far:
# ================================ Configuration Settings ================================
# ================================================================
# Customer Tag Based Discounts
#
# Apply discounts to specific products only for tagged customers
# ================================================================
CUSTOMER_PRODUCT_DISCOUNTS = [
{
customer_tag_match_type: :include,
customer_tags: ["premium-member"],
item_selector_match_type: :include,
item_selector_type: :tag,
item_selectors: ["sale-eligible"],
discount_type: :percent,
discount_amount: 15,
discount_message: "Premium member exclusive discount!",
},
]
# ================================================================
# CustomerValidator
# ================================================================
class CustomerValidator
def initialize(match_type, tags)
@matcher = match_type == :include ? 'any?' : 'none?'
@tags = tags.map { |tag| tag.downcase.strip }
end
def valid?(customer)
customer_tags = customer.tags.map { |tag| tag.downcase.strip }
(@tags & customer_tags).send(@matcher)
end
end
# ================================================================
# ItemSelector
# ================================================================
class ItemSelector
def initialize(match_type, selector_type, selectors)
@match_type = match_type
@matcher = match_type == :include ? 'any?' : 'none?'
@selector_type = selector_type
@selectors = selectors
end
def eligible?(cart_item)
if self.respond_to?(@selector_type)
self.send(@selector_type, cart_item)
else
raise RuntimeError.new('Unknown item selector type')
end
end
def tag(cart_item)
item_tags = cart_item.variant.product.tags.map { |tag| tag.downcase.strip }
@selectors = @selectors.map { |selector| selector.downcase.strip }
(@selectors & item_tags).send(@matcher)
end
end
# ================================================================
# PriceModifier
# ================================================================
class PriceModifier
def initialize(discount_type, discount_amount, discount_message)
@discount_type = discount_type
@discount_message = discount_message
@discount_amount = if discount_type == :percent
1 - (discount_amount * 0.01)
else
Money.new(cents: 100) * discount_amount
end
end
def modify(cart_item)
updated_price = if @discount_type == :percent
cart_item.line_price * @discount_amount
else
[cart_item.line_price - (@discount_amount * cart_item.quantity), Money.zero].max
end
cart_item.change_line_price(updated_price, message: @discount_message)
end
end
The script runs but doesn’t apply the discount properly. I think there’s an issue with how I’m connecting the customer validation with the product selection logic. Can someone help me figure out what’s wrong?