Create a conditional for products containing certain tags

Highlighted
Tourist
7 0 1

 

I have a Bundle Discount script (created with the Script Creator) where customers get % off when buying a combination of certain products (pid). In the BundleDiscount object there are bundle_products which form the bundle. I then have the CAMPAIGNS array that contains all the bundle instances. 
The way the script works is it first applies the discount on the BundleDiscount object that has the lowest index in the CAMPAIGNS array (the first object in the array). So that becomes a problem when users are on a particular bundle page that contains several products forming a discount (let's call it Bundle 1). Once added to the cart, they get the discount as Bundle 1, however, if you add other single products to the cart later on that are also part of a pack (Bundle 2), they might break the first bundle if one of the products is in both bundles, and if Bundle 2 is mentioned before Bundle 1 in the array (because the products will regroup accordingly):
CAMPAIGNS = [   
   Bundle 2,

   Bundle 1
]
This is a no-go, because if users picked the products from a Bundle page, they would want to keep them grouped as they check out.
So how i want to solve it is creating tags only for the bundle product pages, then If a user is on product pages that contain those tags, I want to push the BundleDiscount object that contains these products in the beginning of the CAMPAIGNS array, meaning that this will be the first bundle to get the discount.
I've been trying for a week now, but I am completely clueless on how to approach this problem in Ruby..

Some of the code:

class Campaign
  def initialize(condition, *qualifiers)
    @condition = (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
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 :pid qualifiers.map!(&:to_i) items = cart.line_items.select { |item| qualifiers.include?(item.variant.product.id) && !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 false end def split_out_extra_quantity(cart, items, total_quantity, quantity_required) #some (irrelevant for now) code that split out extra quantity out of a pack 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 = [ # Single bundle BundleDiscount.new( :any, nil, nil, PercentageDiscount.new( 12.01, "Bundle discount applied" ), true, [ {:type => "pid", :qualifiers => ["2631126679652"], :quantity => "1"}, {:type => "pid", :qualifiers => ["2631131365476"], :quantity => "1"} ] ) ].freeze CAMPAIGNS.each do |campaign| campaign.run_with_hooks(Input.cart) end Output.cart = Input.cart

 

 

0 Likes