Class: Coupon::Calculator::PercentageOff

Inherits:
Base
  • Object
show all
Defined in:
app/services/coupon/calculator/percentage_off.rb

Overview

Classic percentage off calculator, applies the percentage_off
specified in the initialization options to each qualifying products
in the line item extractor
line_item_extractor: an instance of ProductFilterLineExtractor
tax_class: :g, :svc, :shp
options:
:percentage_off (required), the percentage to apply, e.g. 0.02 for 2%
:msrp, false by default will calculate off the discounted price, if true will use msrp
:price_with_vat, false by default, if true will calculate off the catalog item price with vat included

Instance Method Summary collapse

Constructor Details

#initialize(line_item_extractor, options = {}) ⇒ PercentageOff

Returns a new instance of PercentageOff.



11
12
13
14
15
# File 'app/services/coupon/calculator/percentage_off.rb', line 11

def initialize(line_item_extractor, options = {})
  raise ':percentage_off option must be specified' unless options[:percentage_off].present?

  super
end

Instance Method Details

#calculate(discount) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'app/services/coupon/calculator/percentage_off.rb', line 17

def calculate(discount)
  @line_item_extractor.discountable_line_items.each do |line_item|
    base_amount = if @options[:msrp]
                    @options[:price_with_vat] ? line_item.msrp_with_vat : line_item.msrp
                  else
                    @options[:price_with_vat] ? line_item.price_with_vat : line_item.discounted_price
                  end
    allocated_unit_amount = -(base_amount * @options[:percentage_off]).ceil(2)
    if @options[:msrp]
      # Remove the already discounted difference between the catalog item price and its msrp
      # Base amount MSRP say is $100, catalog price is $80, difference is $20 (allocated amount)
      # if coupon is 25% off MSRP, then we want to reach $75, we are already at $80
      # So the allocated unit amount is $80 - $75 = $5
      # Therefore we subtract (or add in this case since allocated_unit_amount is already negatie)
      allocated_unit_amount += (base_amount - line_item.discounted_price)
    end
    if @options[:price_with_vat]
      # Remove the taxes
      # Guard against division by zero if tax_rate is nil or -100% (produces Infinity)
      tax_divisor = 1.0 + (line_item.tax_rate || 0)
      allocated_unit_amount = (allocated_unit_amount / tax_divisor).ceil(2) unless tax_divisor.zero?
    end
    allocate_to_line(line_item, discount, allocated_unit_amount)
  end
end