Why does my Shopify script block all discount codes?

igolabs
Tourist
5 0 5

I have successfully built a bundle script using shopify scripts, please see code below.

 

It adds x items to the cart including an identifier and then discounts 10% based on the products.

 

It works apart from one small problem which is really annoying. It does not allow discount codes to be used to any products at all whilst the script is active, so if a customer adds a product which isn't in the script it still blocks the use of it.

 

I need the script to be able to discount the products in the script itself, but still be able to apply discount codes as it's currently blocking them all.

 

Thanks in advance!

 

class Campaign
  def initialize(condition, *qualifiers)
    @condition = condition == :default ? :all? : (condition.to_s + '?').to_sym
    @qualifiers = PostCartAmountQualifier ? [] : [] rescue qualifiers.compact
    @line_item_selector = qualifiers.last unless @line_item_selector
    qualifiers.compact.each do |qualifier|
      is_multi_select = qualifier.instance_variable_get(:@conditions).is_a?(Array)
      if is_multi_select
        qualifier.instance_variable_get(:@conditions).each do |nested_q|
          @post_amount_qualifier = nested_q if nested_q.is_a?(PostCartAmountQualifier)
          @qualifiers << qualifier
        end
      else
        @post_amount_qualifier = qualifier if qualifier.is_a?(PostCartAmountQualifier)
        @qualifiers << qualifier
      end
    end if @qualifiers.empty?
  end

  def qualifies?(cart)
    return true if @qualifiers.empty?
    @unmodified_line_items = cart.line_items.map do |item|
      new_item = item.dup
      new_item.instance_variables.each do |var|
        val = item.instance_variable_get(var)
        new_item.instance_variable_set(var, val.dup) if val.respond_to?(:dup)
      end
      new_item
    end if @post_amount_qualifier
    @qualifiers.send(@condition) do |qualifier|
      is_selector = false
      if qualifier.is_a?(Selector) || qualifier.instance_variable_get(:@conditions).any? { |q| q.is_a?(Selector) }
        is_selector = true
      end rescue nil
      if is_selector
        raise "Missing line item match type" if @li_match_type.nil?
        cart.line_items.send(@li_match_type) { |item| qualifier.match?(item) }
      else
        qualifier.match?(cart, @line_item_selector)
      end
    end
  end

  def run_with_hooks(cart)
    before_run(cart) if respond_to?(:before_run)
    run(cart)
    after_run(cart)
  end

  def after_run(cart)
    @discount.apply_final_discount if @discount && @discount.respond_to?(:apply_final_discount)
    revert_changes(cart) unless @post_amount_qualifier.nil? || @post_amount_qualifier.match?(cart)
  end

  def revert_changes(cart)
    cart.instance_variable_set(:@line_items, @unmodified_line_items)
  end
end

class BundleDiscount < Campaign
  def initialize(condition, customer_qualifier, cart_qualifier, discount, full_bundles_only, bundle_products)
    super(condition, customer_qualifier, cart_qualifier, nil)
    @bundle_products = bundle_products
    @discount = discount
    @full_bundles_only = full_bundles_only
    @split_items = []
    @bundle_items = []
  end

  def check_bundles(cart)
      bundled_items = @bundle_products.map do |bitem|
        quantity_required = bitem[:quantity].to_i
        qualifiers = bitem[:qualifiers]
        type = bitem[:type].to_sym
        case type
          when :ptype
            items = cart.line_items.select { |item| qualifiers.include?(item.variant.product.product_type) && !item.discounted? }
          when :ptag
            items = cart.line_items.select { |item| (qualifiers & item.variant.product.tags).length > 0 && !item.discounted? }
          when :pid
            qualifiers.map!(&:to_i)
            items = cart.line_items.select { |item| qualifiers.include?(item.variant.product.id) && !item.discounted? }
          when :vid
            qualifiers.map!(&:to_i)
            items = cart.line_items.select { |item| qualifiers.include?(item.variant.id) && !item.discounted? }
          when :vsku
            items = cart.line_items.select { |item| (qualifiers & item.variant.skus).length > 0 && !item.discounted? }
        end

        total_quantity = items.reduce(0) { |total, item| total + item.quantity }
        {
          has_all: total_quantity >= quantity_required,
          total_quantity: total_quantity,
          quantity_required: quantity_required,
          total_possible: (total_quantity / quantity_required).to_i,
          items: items
        }
      end

      max_bundle_count = bundled_items.map{ |bundle| bundle[:total_possible] }.min if @full_bundles_only
      if bundled_items.all? { |item| item[:has_all] }
        if @full_bundles_only
          bundled_items.each do |bundle|
            bundle_quantity = bundle[:quantity_required] * max_bundle_count
            split_out_extra_quantity(cart, bundle[:items], bundle[:total_quantity], bundle_quantity)
          end
        else
          bundled_items.each do |bundle|
            bundle[:items].each do |item|
              @bundle_items << item
              cart.line_items.delete(item)
            end
          end
        end
        return true
      end
      false
  end

  def split_out_extra_quantity(cart, items, total_quantity, quantity_required)
    items_to_split = quantity_required
    items.each do |item|
      break if items_to_split == 0
      if item.quantity > items_to_split
        @bundle_items << item.split({take: items_to_split})
        @split_items << item
        items_to_split = 0
      else
        @bundle_items << item
        split_quantity = item.quantity
        items_to_split -= split_quantity
      end
      cart.line_items.delete(item)
    end
    cart.line_items.concat(@split_items)
    @split_items.clear
  end

  def run(cart)
    raise "Campaign requires a discount" unless @discount
    return unless qualifies?(cart)

    if check_bundles(cart)
      @bundle_items.each { |item| @discount.apply(item) }
    end
    @bundle_items.reverse.each { |item| cart.line_items.prepend(item) }
  end
end

class Qualifier
  def partial_match(match_type, item_info, possible_matches)
    match_type = (match_type.to_s + '?').to_sym
    if item_info.kind_of?(Array)
      possible_matches.any? do |possibility|
        item_info.any? do |search|
          search.send(match_type, possibility)
        end
      end
    else
      possible_matches.any? do |possibility|
        item_info.send(match_type, possibility)
      end
    end
  end

  def compare_amounts(compare, comparison_type, compare_to)
    case comparison_type
      when :greater_than
        return compare > compare_to
      when :greater_than_or_equal
        return compare >= compare_to
      when :less_than
        return compare < compare_to
      when :less_than_or_equal
        return compare <= compare_to
      when :equal_to
        return compare == compare_to
      else
        raise "Invalid comparison type"
    end
  end
end

class ExcludeDiscountCodes < Qualifier
  def initialize(behaviour, message, match_type = :reject_except, discount_codes = [])
    @reject = behaviour == :apply_script
    @message = message == "" ? "Discount codes cannot be used with this offer" : message
    @match_type = match_type
    @discount_codes = discount_codes.map(&:downcase)
  end

  def match?(cart, selector = nil)
    return true if cart.discount_code.nil?
    return false if !@reject
    discount_code = cart.discount_code.code.downcase
    should_reject = true
    case @match_type
      when :reject_except
        should_reject = !@discount_codes.include?(discount_code)
      when :accept_except
        should_reject = @discount_codes.include?(discount_code)
    end
    if should_reject
      cart.discount_code.reject({message: @message})
    end
    return true
  end
end

class PercentageDiscount
  def initialize(percent, message)
    @discount = (100 - percent) / 100.0
    @message = message
  end

  def apply(line_item)
    line_item.change_line_price(line_item.line_price * @discount, message: @message)
  end
end

CAMPAIGNS = [
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"},    {:type => "vid", :qualifiers => ["19343338700896"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"},	{:type => "vid", :qualifiers => ["19343434514528"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"},	{:type => "vid", :qualifiers => ["19343123120224"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"},	{:type => "vid", :qualifiers => ["19343386378336"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["19342537359456"], :quantity => "1"}, {:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"},  {:type => "vid", :qualifiers => ["19350794207328"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["19342537359456"], :quantity => "1"}, {:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"},  {:type => "vid", :qualifiers => ["12245771944052"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["12245773123700"], :quantity => "1"}, {:type => "vid", :qualifiers => ["19350794207328"], :quantity => "1"},  {:type => "vid", :qualifiers => ["19351013884000"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["19351156064352"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18356506624096"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["19350079733856"], :quantity => "1"},	{:type => "vid", :qualifiers => ["13568284196960"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["18356472283232"], :quantity => "1"},	{:type => "vid", :qualifiers => ["13568284196960"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["18356472283232"], :quantity => "1"},	{:type => "vid", :qualifiers => ["19343338700896"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["18356472283232"], :quantity => "1"},	{:type => "vid", :qualifiers => ["19343434514528"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["18356472283232"], :quantity => "1"},	{:type => "vid", :qualifiers => ["19343123120224"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    ExcludeDiscountCodes.new(
      :apply_script,
      "Discount codes are not compatible with our Sets",
      :reject_except,
      []
    ),
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    false,
    [{:type => "vid", :qualifiers => ["18356472283232"], :quantity => "1"},	{:type => "vid", :qualifiers => ["19343386378336"], :quantity => "1"},	{:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
].freeze

CAMPAIGNS.each do |campaign|
  campaign.run_with_hooks(Input.cart)
end

Output.cart = Input.cart
Replies 2 (2)

Jason
Shopify Expert
11190 225 2282

This code has lots of instances where you reject discount codes. If you didn't want the rejection, why add those lines in? I don't have full context here so could be asking some crazy (and silly) questions.

 

What part of this script did you not want the rejection to happen on?

 

(also, app devs spamming their products instead of helping will find their posts magically marked as spam. if you posted - not talking about you igolabs - and it's now gone, that's why)

 

★ I jump on these forums in my free time to help and share some insights. Not looking to be hired, and not looking for work. http://freakdesign.com.au ★
igolabs
Tourist
5 0 5

Sorry for lack of context Jason,

 

I'm not too hot on Ruby as you can tell, the script blocks all discount codes on every transaction whereas i only want them to be blocked when purchasing a bundle.

 

We have a temporary situation where we cannot have a SKU for the bundles and have to use permalinks + scripts to apply the discount. The permalinks add 2/3 products + a £0.00 value identifier product for our distributor.

The script sucessfully triggers when the cart recognises the 3/4 products in the cart, and stops discount codes being applied. However if i just added 1 of the products from the bundle or a product not in any of the bundles it still blocks the discount. I want discounts only to be blocked if the 3/4 VID's match.

 

This could be a Scripts issue which i can't get round this way.

 

Another thing i've thought of could be adding a £0.00 discount code but as far as i can tell you can't combine cart permalinks and shareable discount url's.

 

It's the last piece of this complicated puzzle to stop abuse of bundles from people with discount codes. Hopefully this gives you a bit more context!

 

P.S I've added the code before i added the discount code stuff in below.

class Campaign
  def initialize(condition, *qualifiers)
    @condition = condition == :default ? :all? : (condition.to_s + '?').to_sym
    @qualifiers = PostCartAmountQualifier ? [] : [] rescue qualifiers.compact
    @line_item_selector = qualifiers.last unless @line_item_selector
    qualifiers.compact.each do |qualifier|
      is_multi_select = qualifier.instance_variable_get(:@conditions).is_a?(Array)
      if is_multi_select
        qualifier.instance_variable_get(:@conditions).each do |nested_q| 
          @post_amount_qualifier = nested_q if nested_q.is_a?(PostCartAmountQualifier)
          @qualifiers << qualifier
        end
      else
        @post_amount_qualifier = qualifier if qualifier.is_a?(PostCartAmountQualifier)
        @qualifiers << qualifier
      end
    end if @qualifiers.empty?
  end
  
  def qualifies?(cart)
    return true if @qualifiers.empty?
    @unmodified_line_items = cart.line_items.map do |item|
      new_item = item.dup
      new_item.instance_variables.each do |var|
        val = item.instance_variable_get(var)
        new_item.instance_variable_set(var, val.dup) if val.respond_to?(:dup)
      end
      new_item  
    end if @post_amount_qualifier
    @qualifiers.send(@condition) do |qualifier|
      is_selector = false
      if qualifier.is_a?(Selector) || qualifier.instance_variable_get(:@conditions).any? { |q| q.is_a?(Selector) }
        is_selector = true
      end rescue nil
      if is_selector
        raise "Missing line item match type" if @li_match_type.nil?
        cart.line_items.send(@li_match_type) { |item| qualifier.match?(item) }
      else
        qualifier.match?(cart, @line_item_selector)
      end
    end
  end

  def revert_changes(cart)
    cart.instance_variable_set(:@line_items, @unmodified_line_items)
  end
end

class BundleDiscount < Campaign
  def initialize(condition, customer_qualifier, cart_qualifier, discount, full_bundles_only, bundle_products)
    super(condition, customer_qualifier, cart_qualifier)
    @bundle_products = bundle_products
    @discount = discount
    @full_bundles_only = full_bundles_only
    @split_items = []
    @bundle_items = []
  end
  
  def check_bundles(cart)
      bundled_items = @bundle_products.map do |bitem|
        quantity_required = bitem[:quantity].to_i
        qualifiers = bitem[:qualifiers]
        type = bitem[:type].to_sym
        case type
          when :ptype
            items = cart.line_items.select { |item| qualifiers.include?(item.variant.product.product_type) }
          when :ptag
            items = cart.line_items.select { |item| (qualifiers & item.variant.product.tags).length > 0 }
          when :pid
            qualifiers.map!(&:to_i)
            items = cart.line_items.select { |item| qualifiers.include?(item.variant.product.id) }
          when :vid
            qualifiers.map!(&:to_i)
            items = cart.line_items.select { |item| qualifiers.include?(item.variant.id) }
        end
        
        total_quantity = items.reduce(0) { |total, item| total + item.quantity }
        {
          has_all: total_quantity >= quantity_required,
          total_quantity: total_quantity,
          quantity_required: quantity_required,
          total_possible: (total_quantity / quantity_required).to_i,
          items: items
        }
      end
      
      max_bundle_count = bundled_items.map{ |bundle| bundle[:total_possible] }.min if @full_bundles_only
      if bundled_items.all? { |item| item[:has_all] }
        if @full_bundles_only
          bundled_items.each do |bundle|
            bundle_quantity = bundle[:quantity_required] * max_bundle_count
            split_out_extra_quantity(cart, bundle[:items], bundle[:total_quantity], bundle_quantity)
          end
        else
          bundled_items.each do |bundle|
            bundle[:items].each do |item| 
              @bundle_items << item 
              cart.line_items.delete(item)
            end
          end
        end
        return true
      end
      false
  end
  
  def split_out_extra_quantity(cart, items, total_quantity, quantity_required)
    items_to_split = quantity_required
    items.each do |item|
      break if items_to_split == 0
      if item.quantity > items_to_split
        @bundle_items << item.split({take: items_to_split})
        @split_items << item
        items_to_split = 0
      else
        @bundle_items << item
        split_quantity = item.quantity
        items_to_split -= split_quantity
      end
      cart.line_items.delete(item)
    end
    cart.line_items.concat(@split_items)
    @split_items.clear
  end
  
  def run(cart)
    raise "Campaign requires a discount" unless @discount
    return unless qualifies?(cart)
    
    if check_bundles(cart)
      @bundle_items.each { |item| @discount.apply(item) }
    end
    @bundle_items.reverse.each { |item| cart.line_items.prepend(item) }
  end
end

class PercentageDiscount
  def initialize(percent, message)
    @discount = (100 - percent) / 100.0
    @message = message
  end

  def apply(line_item)
    line_item.change_line_price(line_item.line_price * @discount, message: @message)
  end
end

CAMPAIGNS = [
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["12245773123700"], :quantity => "1"}, {:type => "vid", :qualifiers => ["19350794207328"], :quantity => "1"},  {:type => "vid", :qualifiers => ["19351013884000"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["19343338700896"], :quantity => "1"}, {:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["18356506624096"], :quantity => "1"}, {:type => "vid", :qualifiers => ["19351156064352"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["19343434514528"], :quantity => "1"}, {:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["18356472283232"], :quantity => "1"}, {:type => "vid", :qualifiers => ["13568284196960"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["19343338700896"], :quantity => "1"}, {:type => "vid", :qualifiers => ["18356472283232"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"}, {:type => "vid", :qualifiers => ["19343123120224"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"}, {:type => "vid", :qualifiers => ["19343386378336"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["19343123120224"], :quantity => "1"}, {:type => "vid", :qualifiers => ["18356472283232"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["19343386378336"], :quantity => "1"}, {:type => "vid", :qualifiers => ["18356472283232"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["19342537359456"], :quantity => "1"}, {:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"},  {:type => "vid", :qualifiers => ["12245771944052"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["19342537359456"], :quantity => "1"}, {:type => "vid", :qualifiers => ["19350922264672"], :quantity => "1"},  {:type => "vid", :qualifiers => ["19350794207328"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["19350079733856"], :quantity => "1"}, {:type => "vid", :qualifiers => ["13568284196960"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
  BundleDiscount.new(
    :all,
    nil,
    nil,
    PercentageDiscount.new(
      10,
      "Save 10% with our Sets"
    ),
    true,
    [{:type => "vid", :qualifiers => ["19343434514528"], :quantity => "1"}, {:type => "vid", :qualifiers => ["18356472283232"], :quantity => "1"},  {:type => "vid", :qualifiers => ["18844374270048"], :quantity => "1"}]
  ),
].freeze

CAMPAIGNS.each do |campaign|
  campaign.run(Input.cart)
end

Output.cart = Input.cart