BOGO + 1 Size Larger Shopify Sample
# ================================ Customizable Settings ================================
# ================================================================
# Buy V of Product W, Get X of Product Y for Z Discount
#
# Buy a certain number of matching items, get a certain number of
# a different set of matching items with the entered discount
# applied. For example:
#
#   "Buy 2 t-shirts, get 1 hat for 10% off"
#
#   - 'buy_product_selector_match_type' determines whether we look
#     for products that do or don't match the entered selectors.
#     Can be:
#       - ':include' to check if the product does match
#       - ':exclude' to make sure the product doesn't match
#   - 'buy_product_selector_type' determines how eligible products
#     will be identified. Can be:
#       - ':tag' to find products by tag
#       - ':type' to find products by type
#       - ':vendor' to find products by vendor
#       - ':product_id' to find products by ID
#       - ':variant_id' to find products by variant ID
#       - ':subscription' to find subscription products
#       - ':all' for all products
#   - 'buy_product_selectors' is a list of identifiers (from above)
#     for qualifying products. Product/Variant ID lists should only
#     contain numbers (ie. no quotes). If ':all' is used, this
#     can also be 'nil'.
#   - 'quantity_to_buy' is the number of products needed to
#     qualify
#   - 'get_selector_match_type' is the same idea as the "Buy"
#     version above
#   - 'get_product_selector_type' is the same idea as the "Buy"
#     version above
#   - 'get_product_selectors' is the same idea as the "Buy"
#     version above
#   - 'quantity_to_discount' is the number of products to discount
#   - 'allow_incomplete_bundle' determines whether a portion of
#     the items to discount can be discounted, or all items
#     need to be present. Can be:
#       - 'true'
#       - 'false'
#   - 'discount_type' is the type of discount to provide. Can be
#     either:
#       - ':percent'
#       - ':dollar'
#   - 'discount_amount' is the percentage/dollar discount to
#     apply (per item)
#   - 'discount_message' is the message to show when a discount
#     is applied
# ================================================================
$singular_discount = true; 
BUYVOFW_GETXOFY_FORZ = [
{
buy_product_selector_match_type: :include,
buy_product_selector_type: :variant_id,
buy_product_selectors: [40109910098116],
quantity_to_buy: 1,
get_product_selector_match_type: :include,
get_product_selector_type: :variant_id,
get_product_selectors: [40109910130884],
quantity_to_discount: 1,
allow_incomplete_bundle: false,
discount_type: :dollar,
discount_amount: 100,
buy_product_selector_match_type: :include,
buy_product_selector_type: :variant_id,
buy_product_selectors: [40109910130884],
quantity_to_buy: 1,
get_product_selector_match_type: :include,
get_product_selector_type: :variant_id,
get_product_selectors: [40109910163652],
quantity_to_discount: 1,
allow_incomplete_bundle: false,
discount_type: :dollar,
discount_amount: 100,
buy_product_selector_match_type: :include,
buy_product_selector_type: :variant_id,
buy_product_selectors: [40109910163652],
quantity_to_buy: 1,
get_product_selector_match_type: :include,
get_product_selector_type: :variant_id,
get_product_selectors: [40109910196420],
quantity_to_discount: 1,
allow_incomplete_bundle: false,
discount_type: :dollar,
discount_amount: 100,
buy_product_selector_match_type: :include,
buy_product_selector_type: :variant_id,
buy_product_selectors: [40109910196420],
quantity_to_buy: 1,
get_product_selector_match_type: :include,
get_product_selector_type: :variant_id,
get_product_selectors: [40109910261956],
quantity_to_discount: 1,
allow_incomplete_bundle: false,
discount_type: :dollar,
discount_amount: 100,
discount_message: 'Congratulations! You won a FREE Mommas Comfy Maternity Bra!',
},
]

# ================================ Script Code (do not edit) ================================
# ================================================================
# ProductSelector
#
# Finds matching products by the entered criteria.
# ================================================================
class ProductSelector
  def initialize(match_type, selector_type, selectors)
    @match_type = match_type
    @comparator = match_type == :include ? 'any?' : 'none?'
    @selector_type = selector_type
    @selectors = selectors
  end

  def match?(line_item)
    if self.respond_to?(@selector_type)
      self.send(@selector_type, line_item)
    else
      raise RuntimeError.new('Invalid product selector type')
    end
  end

  def tag(line_item)
    product_tags = line_item.variant.product.tags.map { |tag| tag.downcase.strip }
    @selectors = @selectors.map { |selector| selector.downcase.strip }
    (@selectors & product_tags).send(@comparator)
  end

  def type(line_item)
    @selectors = @selectors.map { |selector| selector.downcase.strip }
    (@match_type == :include) == @selectors.include?(line_item.variant.product.product_type.downcase.strip)
  end

  def vendor(line_item)
    @selectors = @selectors.map { |selector| selector.downcase.strip }
    (@match_type == :include) == @selectors.include?(line_item.variant.product.vendor.downcase.strip)
  end

  def product_id(line_item)
    (@match_type == :include) == @selectors.include?(line_item.variant.product.id)
  end

  def variant_id(line_item)
    (@match_type == :include) == @selectors.include?(line_item.variant.id)
  end

  def subscription(line_item)
    !line_item.selling_plan_id.nil?
  end

  def all(line_item)
    true
  end
end

# ================================================================
# DiscountApplicator
#
# Applies the entered discount to the supplied line item.
# ================================================================
class DiscountApplicator
  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 apply(line_item)
    new_line_price = if @discount_type == :percent
      line_item.line_price * @discount_amount
    else
      [line_item.line_price - (@discount_amount * line_item.quantity), Money.zero].max
    end

    line_item.change_line_price(new_line_price, message: @discount_message)
  end
end

# ================================================================
# DiscountLoop
#
# Loops through the supplied line items and discounts the supplied
# number of items by the supplied discount.
# ================================================================
class DiscountLoop
  def initialize(discount_applicator)
    @discount_applicator = discount_applicator
  end

  def loop_items(cart, line_items, num_to_discount)
    line_items.each do |line_item|
      break if num_to_discount <= 0

      if line_item.quantity > num_to_discount
        split_line_item = line_item.split(take: num_to_discount)
        @discount_applicator.apply(split_line_item)
        position = cart.line_items.find_index(line_item)
        cart.line_items.insert(position + 1, split_line_item)
        break
      else
        @discount_applicator.apply(line_item)
        num_to_discount -= line_item.quantity
      end
    end
  end
end

# ================================================================
# BuyVofWGetXofYForZCampaign
#
# Buy a certain number of matching items, get a certain number of
# a different set of matching items with the entered discount
# applied.
# ================================================================
class BuyVofWGetXofYForZCampaign
  def initialize(campaigns)
    @campaigns = campaigns
  end

  def run(cart)
    @campaigns.each do |campaign|
      buy_product_selector = ProductSelector.new(
        campaign[:buy_product_selector_match_type],
        campaign[:buy_product_selector_type],
        campaign[:buy_product_selectors],
      )

      get_product_selector = ProductSelector.new(
        campaign[:get_product_selector_match_type],
        campaign[:get_product_selector_type],
        campaign[:get_product_selectors],
      )

      buy_items = []
      get_items = []

      cart.line_items.each do |line_item|
        buy_items.push(line_item) if buy_product_selector.match?(line_item)
        get_items.push(line_item) if get_product_selector.match?(line_item)
      end

      next if buy_items.empty? || get_items.empty?

      get_items = get_items.sort_by { |line_item| line_item.variant.price }
      quantity_to_buy = campaign[:quantity_to_buy]
      quantity_to_discount = campaign[:quantity_to_discount]
      buy_offers = (buy_items.map(&:quantity).reduce(0, :+) / quantity_to_buy).floor

      if campaign[:allow_incomplete_bundle]
        number_of_bundles = buy_offers
      else
        get_offers = (get_items.map(&:quantity).reduce(0, :+) / quantity_to_discount).floor
        number_of_bundles = [buy_offers, get_offers].min
      end

      number_of_discountable_items = number_of_bundles * quantity_to_discount

      next unless number_of_discountable_items > 0

      discount_applicator = DiscountApplicator.new(
        campaign[:discount_type],
        campaign[:discount_amount],
        campaign[:discount_message]
      )

      if $singular_discount
       discount_loop = DiscountLoop.new(discount_applicator)
       discount_loop.loop_items(cart, get_items, 1)
       $singular_discount = false
      end
    end
  end
end

CAMPAIGNS = [
  BuyVofWGetXofYForZCampaign.new(BUYVOFW_GETXOFY_FORZ),
]

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

Output.cart = Input.cart
LIVE STORE
Gray
XS - 40109910098116 
S - 40109910130884
M - 40109910163652
L - 40109910196420
XL - 40109910261956
XXL - 40934024577220

Pink
XS - 40109910294724
S - 40109910327492
M - 40109910360260
L - 40109910393028
XL - 40109910458564
XXL - 40934025167044

Peach
XS - 40109910491332
S - 40109910524100
M - 40109910556868
L - 40109910589636
XL - 40109910655172
XXL - 40934025560260

Black
XS - 40262009159876
S - 40262010568900
M - 40262011355332
L - 40262012076228
XL - 40262013812932
XXL - 40934025232580
- - - - - 
DEMO STORE - Grey end on Line 103
Grey
XS - 41695385977029
S - 41695386009797
M - 41695386042565
L - 41695386075333
XL - 41695386108101
XXL - 41695803113669

Pink
XS - 41695386140869
S - 41695386173637
M - 41695386206405
L - 41695386239173
XL - 41695386271941
XXL - 41695803146437

Peach
XS - 40109910491332
S - 40109910524100
M - 40109910556868
L - 40109910589636
XL - 40109910655172
XXL - 

Black
XS - 
S - 
M - 
L - 
XL - 
XXL - 

buy_product_selector_match_type: :include,
buy_product_selector_type: :variant_id,
buy_product_selectors: [39364450713796], <--- Change to this variant id of size
quantity_to_buy: 1,
get_product_selector_match_type: :include,
get_product_selector_type: :variant_id,
get_product_selectors: [39364452352196], <--- Change to variant id of larger size
quantity_to_discount: 1,
# ================================ Customizable Settings ================================
# ================================================================
# Buy V of Product W, Get X of Product Y for Z Discount
#
# Buy a certain number of matching items, get a certain number of
# a different set of matching items with the entered discount
# applied. For example:
#
#   "Buy 2 t-shirts, get 1 hat for 10% off"
#
#   - 'buy_product_selector_match_type' determines whether we look
#     for products that do or don't match the entered selectors.
#     Can be:
#       - ':include' to check if the product does match
#       - ':exclude' to make sure the product doesn't match
#   - 'buy_product_selector_type' determines how eligible products
#     will be identified. Can be:
#       - ':tag' to find products by tag
#       - ':type' to find products by type
#       - ':vendor' to find products by vendor
#       - ':product_id' to find products by ID
#       - ':variant_id' to find products by variant ID
#       - ':subscription' to find subscription products
#       - ':all' for all products
#   - 'buy_product_selectors' is a list of identifiers (from above)
#     for qualifying products. Product/Variant ID lists should only
#     contain numbers (ie. no quotes). If ':all' is used, this
#     can also be 'nil'.
#   - 'quantity_to_buy' is the number of products needed to
#     qualify
#   - 'get_selector_match_type' is the same idea as the "Buy"
#     version above
#   - 'get_product_selector_type' is the same idea as the "Buy"
#     version above
#   - 'get_product_selectors' is the same idea as the "Buy"
#     version above
#   - 'quantity_to_discount' is the number of products to discount
#   - 'allow_incomplete_bundle' determines whether a portion of
#     the items to discount can be discounted, or all items
#     need to be present. Can be:
#       - 'true'
#       - 'false'
#   - 'discount_type' is the type of discount to provide. Can be
#     either:
#       - ':percent'
#       - ':dollar'
#   - 'discount_amount' is the percentage/dollar discount to
#     apply (per item)
#   - 'discount_message' is the message to show when a discount
#     is applied
# ================================================================
$singular_discount = true; 
BUYVOFW_GETXOFY_FORZ = [
  {
    buy_product_selector_match_type: :include,
    buy_product_selector_type: :variant_id,
    buy_product_selectors: [39364450713796],
    quantity_to_buy: 1,
    get_product_selector_match_type: :include,
    get_product_selector_type: :variant_id,
    get_product_selectors: [39364452352196],
    quantity_to_discount: 1,
    allow_incomplete_bundle: false,
    discount_type: :dollar,
    discount_amount: 100,
    discount_message: 'Buy Mommas Comfy Maternity Bra and get a larger size for free!',
  },
  {
    buy_product_selector_match_type: :include,
    buy_product_selector_type: :variant_id,
    buy_product_selectors: [39364451664068],
    quantity_to_buy: 1,
    get_product_selector_match_type: :include,
    get_product_selector_type: :variant_id,
    get_product_selectors: [39364450713796],
    quantity_to_discount: 1,
    allow_incomplete_bundle: false,
    discount_type: :dollar,
    discount_amount: 100,
    discount_message: 'Buy Mommas Comfy Maternity Bra and get a larger size for free! B/C',
  },
  {
    buy_product_selector_match_type: :include,
    buy_product_selector_type: :variant_id,
    buy_product_selectors: [39364450681028],
    quantity_to_buy: 1,
    get_product_selector_match_type: :include,
    get_product_selector_type: :variant_id,
    get_product_selectors: [39364451664068],
    quantity_to_discount: 1,
    allow_incomplete_bundle: false,
    discount_type: :dollar,
    discount_amount: 100,
    discount_message: 'Buy Mommas Comfy Maternity Bra and get a larger size for free! A/B',
  },
]

# ================================ Script Code (do not edit) ================================
# ================================================================
# ProductSelector
#
# Finds matching products by the entered criteria.
# ================================================================
class ProductSelector
  def initialize(match_type, selector_type, selectors)
    @match_type = match_type
    @comparator = match_type == :include ? 'any?' : 'none?'
    @selector_type = selector_type
    @selectors = selectors
  end

  def match?(line_item)
    if self.respond_to?(@selector_type)
      self.send(@selector_type, line_item)
    else
      raise RuntimeError.new('Invalid product selector type')
    end
  end

  def tag(line_item)
    product_tags = line_item.variant.product.tags.map { |tag| tag.downcase.strip }
    @selectors = @selectors.map { |selector| selector.downcase.strip }
    (@selectors & product_tags).send(@comparator)
  end

  def type(line_item)
    @selectors = @selectors.map { |selector| selector.downcase.strip }
    (@match_type == :include) == @selectors.include?(line_item.variant.product.product_type.downcase.strip)
  end

  def vendor(line_item)
    @selectors = @selectors.map { |selector| selector.downcase.strip }
    (@match_type == :include) == @selectors.include?(line_item.variant.product.vendor.downcase.strip)
  end

  def product_id(line_item)
    (@match_type == :include) == @selectors.include?(line_item.variant.product.id)
  end

  def variant_id(line_item)
    (@match_type == :include) == @selectors.include?(line_item.variant.id)
  end

  def subscription(line_item)
    !line_item.selling_plan_id.nil?
  end

  def all(line_item)
    true
  end
end

# ================================================================
# DiscountApplicator
#
# Applies the entered discount to the supplied line item.
# ================================================================
class DiscountApplicator
  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 apply(line_item)
    new_line_price = if @discount_type == :percent
      line_item.line_price * @discount_amount
    else
      [line_item.line_price - (@discount_amount * line_item.quantity), Money.zero].max
    end

    line_item.change_line_price(new_line_price, message: @discount_message)
  end
end

# ================================================================
# DiscountLoop
#
# Loops through the supplied line items and discounts the supplied
# number of items by the supplied discount.
# ================================================================
class DiscountLoop
  def initialize(discount_applicator)
    @discount_applicator = discount_applicator
  end

  def loop_items(cart, line_items, num_to_discount)
    line_items.each do |line_item|
      break if num_to_discount <= 0

      if line_item.quantity > num_to_discount
        split_line_item = line_item.split(take: num_to_discount)
        @discount_applicator.apply(split_line_item)
        position = cart.line_items.find_index(line_item)
        cart.line_items.insert(position + 1, split_line_item)
        break
      else
        @discount_applicator.apply(line_item)
        num_to_discount -= line_item.quantity
      end
    end
  end
end

# ================================================================
# BuyVofWGetXofYForZCampaign
#
# Buy a certain number of matching items, get a certain number of
# a different set of matching items with the entered discount
# applied.
# ================================================================
class BuyVofWGetXofYForZCampaign
  def initialize(campaigns)
    @campaigns = campaigns
  end

  def run(cart)
    @campaigns.each do |campaign|
      buy_product_selector = ProductSelector.new(
        campaign[:buy_product_selector_match_type],
        campaign[:buy_product_selector_type],
        campaign[:buy_product_selectors],
      )

      get_product_selector = ProductSelector.new(
        campaign[:get_product_selector_match_type],
        campaign[:get_product_selector_type],
        campaign[:get_product_selectors],
      )

      buy_items = []
      get_items = []

      cart.line_items.each do |line_item|
        buy_items.push(line_item) if buy_product_selector.match?(line_item)
        get_items.push(line_item) if get_product_selector.match?(line_item)
      end

      next if buy_items.empty? || get_items.empty?

      get_items = get_items.sort_by { |line_item| line_item.variant.price }
      quantity_to_buy = campaign[:quantity_to_buy]
      quantity_to_discount = campaign[:quantity_to_discount]
      buy_offers = (buy_items.map(&:quantity).reduce(0, :+) / quantity_to_buy).floor

      if campaign[:allow_incomplete_bundle]
        number_of_bundles = buy_offers
      else
        get_offers = (get_items.map(&:quantity).reduce(0, :+) / quantity_to_discount).floor
        number_of_bundles = [buy_offers, get_offers].min
      end

      number_of_discountable_items = number_of_bundles * quantity_to_discount

      next unless number_of_discountable_items > 0

      discount_applicator = DiscountApplicator.new(
        campaign[:discount_type],
        campaign[:discount_amount],
        campaign[:discount_message]
      )

      if $singular_discount
       discount_loop = DiscountLoop.new(discount_applicator)
       discount_loop.loop_items(cart, get_items, 1)
       $singular_discount = false
      end
    end
  end
end

CAMPAIGNS = [
  BuyVofWGetXofYForZCampaign.new(BUYVOFW_GETXOFY_FORZ),
]

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

Output.cart = Input.cart

BOGO + 1 Size Larger Shopify Sample

  • Archivos
  • Index
  • Style
  • Script
  • README
  • CDN Agregar
HTML

================================ Customizable Settings ================================

================================================================

Buy V of Product W, Get X of Product Y for Z Discount

Buy a certain number of matching items, get a certain number of

a different set of matching items with the entered discount

applied. For example:

"Buy 2 t-shirts, get 1 hat for 10% off"

- 'buy_product_selector_match_type' determines whether we look

for products that do or don't match the entered selectors.

Can be:

- ':include' to check if the product does match

- ':exclude' to make sure the product doesn't match

- 'buy_product_selector_type' determines how eligible products

will be identified. Can be:

- ':tag' to find products by tag

- ':type' to find products by type

- ':vendor' to find products by vendor

- ':product_id' to find products by ID

- ':variant_id' to find products by variant ID

- ':subscription' to find subscription products

- ':all' for all products

- 'buy_product_selectors' is a list of identifiers (from above)

for qualifying products. Product/Variant ID lists should only

contain numbers (ie. no quotes). If ':all' is used, this

can also be 'nil'.

- 'quantity_to_buy' is the number of products needed to

qualify

- 'get_selector_match_type' is the same idea as the "Buy"

version above

- 'get_product_selector_type' is the same idea as the "Buy"

version above

- 'get_product_selectors' is the same idea as the "Buy"

version above

- 'quantity_to_discount' is the number of products to discount

- 'allow_incomplete_bundle' determines whether a portion of

the items to discount can be discounted, or all items

need to be present. Can be:

- 'true'

- 'false'

- 'discount_type' is the type of discount to provide. Can be

either:

- ':percent'

- ':dollar'

- 'discount_amount' is the percentage/dollar discount to

apply (per item)

- 'discount_message' is the message to show when a discount

is applied

================================================================

$singular_discount = true; BUYVOFW_GETXOFY_FORZ = [ { buy_product_selector_match_type: :include, buy_product_selector_type: :variant_id, buy_product_selectors: [40109910098116], quantity_to_buy: 1, get_product_selector_match_type: :include, get_product_selector_type: :variant_id, get_product_selectors: [40109910130884], buy_product_selectors: [40109910130884], quantity_to_buy: 1, get_product_selector_match_type: :include, get_product_selector_type: :variant_id, get_product_selectors: [40109910163652], quantity_to_discount: 1, buy_product_selectors: [40109910163652], quantity_to_buy: 1, get_product_selector_match_type: :include, get_product_selector_type: :variant_id, get_product_selectors: [40109910196420], quantity_to_discount: 1, buy_product_selectors: [40109910196420], quantity_to_buy: 1, get_product_selector_match_type: :include, get_product_selector_type: :variant_id, get_product_selectors: [40109910261956], quantity_to_discount: 1, buy_product_selectors: [40109910261956], quantity_to_buy: 1, get_product_selector_match_type: :include, get_product_selector_type: :variant_id, get_product_selectors: [41695803113669], quantity_to_discount: 1, allow_incomplete_bundle: false, discount_type: :dollar, discount_amount: 100, discount_message: 'Buy Mommas Comfy Maternity Bra and get a larger size for free!', }, ]

================================ Script Code (do not edit) ================================

================================================================

ProductSelector

Finds matching products by the entered criteria.

================================================================

class ProductSelector def initialize(match_type, selector_type, selectors) @match_type = match_type @comparator = match_type == :include ? 'any?' : 'none?' @selector_type = selector_type @selectors = selectors end

def match?(line_item) if self.respond_to?(@selector_type) self.send(@selector_type, line_item) else raise RuntimeError.new('Invalid product selector type') end end

def tag(line_item) product_tags = line_item.variant.product.tags.map { |tag| tag.downcase.strip } @selectors = @selectors.map { |selector| selector.downcase.strip } (@selectors & product_tags).send(@comparator) end

def type(line_item) @selectors = @selectors.map { |selector| selector.downcase.strip } (@match_type == :include) == @selectors.include?(line_item.variant.product.product_type.downcase.strip) end

def vendor(line_item) @selectors = @selectors.map { |selector| selector.downcase.strip } (@match_type == :include) == @selectors.include?(line_item.variant.product.vendor.downcase.strip) end

def product_id(line_item) (@match_type == :include) == @selectors.include?(line_item.variant.product.id) end

def variant_id(line_item) (@match_type == :include) == @selectors.include?(line_item.variant.id) end

def subscription(line_item) !line_item.selling_plan_id.nil? end

def all(line_item) true end end

================================================================

DiscountApplicator

Applies the entered discount to the supplied line item.

================================================================

class DiscountApplicator 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 apply(line_item) new_line_price = if @discount_type == :percent line_item.line_price * @discount_amount else [line_item.line_price - (@discount_amount * line_item.quantity), Money.zero].max end

line_item.change_line_price(new_line_price, message: @discount_message)

end end

================================================================

DiscountLoop

Loops through the supplied line items and discounts the supplied

number of items by the supplied discount.

================================================================

class DiscountLoop def initialize(discount_applicator) @discount_applicator = discount_applicator end

def loop_items(cart, line_items, num_to_discount) line_items.each do |line_item| break if num_to_discount <= 0

  if line_item.quantity > num_to_discount
    split_line_item = line_item.split(take: num_to_discount)
    @discount_applicator.apply(split_line_item)
    position = cart.line_items.find_index(line_item)
    cart.line_items.insert(position + 1, split_line_item)
    break
  else
    @discount_applicator.apply(line_item)
    num_to_discount -= line_item.quantity
  end
end

end end

================================================================

BuyVofWGetXofYForZCampaign

Buy a certain number of matching items, get a certain number of

a different set of matching items with the entered discount

applied.

================================================================

class BuyVofWGetXofYForZCampaign def initialize(campaigns) @campaigns = campaigns end

def run(cart) @campaigns.each do |campaign| buy_product_selector = ProductSelector.new( campaign[:buy_product_selector_match_type], campaign[:buy_product_selector_type], campaign[:buy_product_selectors], )

  get_product_selector = ProductSelector.new(
    campaign[:get_product_selector_match_type],
    campaign[:get_product_selector_type],
    campaign[:get_product_selectors],
  )

  buy_items = []
  get_items = []

  cart.line_items.each do |line_item|
    buy_items.push(line_item) if buy_product_selector.match?(line_item)
    get_items.push(line_item) if get_product_selector.match?(line_item)
  end

  next if buy_items.empty? || get_items.empty?

  get_items = get_items.sort_by { |line_item| line_item.variant.price }
  quantity_to_buy = campaign[:quantity_to_buy]
  quantity_to_discount = campaign[:quantity_to_discount]
  buy_offers = (buy_items.map(&:quantity).reduce(0, :+) / quantity_to_buy).floor

  if campaign[:allow_incomplete_bundle]
    number_of_bundles = buy_offers
  else
    get_offers = (get_items.map(&:quantity).reduce(0, :+) / quantity_to_discount).floor
    number_of_bundles = [buy_offers, get_offers].min
  end

  number_of_discountable_items = number_of_bundles * quantity_to_discount

  next unless number_of_discountable_items > 0

  discount_applicator = DiscountApplicator.new(
    campaign[:discount_type],
    campaign[:discount_amount],
    campaign[:discount_message]
  )

  if $singular_discount
   discount_loop = DiscountLoop.new(discount_applicator)
   discount_loop.loop_items(cart, get_items, 1)
   $singular_discount = false
  end
end

end end

CAMPAIGNS = [ BuyVofWGetXofYForZCampaign.new(BUYVOFW_GETXOFY_FORZ), ]

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

class Intelligems def initialize(discount_property = '_igp', allow_free = false) @volume_discount_property = '_igvd' @volume_discount_message_property = '_igvd_message' @depreciated_property = '_igLineItemDiscount' @discount_property = discount_property @allow_free = allow_free end

def discount_product(line_item) ig_price = Money.new(cents: line_item.properties[@discount_property])

discount = line_item.line_price - ig_price
if discount > Money.zero
  discount *= line_item.quantity
  line_item.change_line_price(line_item.line_price - discount, message: 'Discount')
end

end

def depreciated_discount_product(line_item) discount = Money.new(cents: line_item.properties[@depreciated_property]) discount *= line_item.quantity

if @allow_free or discount < line_item.line_price
  line_item.change_line_price(line_item.line_price - discount, message: 'Discount')
end

end

def volume_discount(line_item) discount = Money.new(cents: line_item.properties[@volume_discount_property]) discount *= line_item.quantity

if discount < line_item.line_price
  message = line_item.properties[@volume_discount_message_property]
  line_item.change_line_price(line_item.line_price - discount, message: message)
end

end

def run(cart) cart.line_items.each do |line_item| # line_item.change_properties({'_igp' => '200'}, message: "hi") if !line_item.properties[@discount_property].nil? && !line_item.properties[@discount_property].empty? discount_product(line_item) elsif !line_item.properties[@volume_discount_property].nil? && !line_item.properties[@volume_discount_property].empty? volume_discount(line_item) elsif !line_item.properties[@depreciated_property].nil? && !line_item.properties[@depreciated_property].empty? depreciated_discount_product(line_item) end end end end

intelligems = Intelligems.new() intelligems.run(Input.cart)

Output.cart = Input.cart

PLEASE WAIT...