Class: Spree::Promotion::Actions::CreateQuantityAdjustments

Inherits:
CreateItemAdjustments show all
Defined in:
app/models/spree/promotion/actions/create_quantity_adjustments.rb

Defined Under Namespace

Classes: PartialLineItem

Instance Method Summary collapse

Methods inherited from CreateItemAdjustments

#perform, #remove_from

Methods included from AdjustmentSource

#deals_with_adjustments_for_deleted_source

Methods included from CalculatedAdjustments

#calculator_type, #calculator_type=

Methods inherited from Spree::PromotionAction

#perform, #remove_from, #to_partial_path

Methods inherited from Base

display_includes, #initialize_preference_defaults, page, preference

Methods included from Spree::Preferences::Preferable

#default_preferences, #defined_preferences, #get_preference, #has_preference!, #has_preference?, #preference_default, #preference_type, #set_preference

Instance Method Details

#compute_amount(line_item) ⇒ Object

Computes the amount for the adjustment based on the line item and any other applicable items in the order. The rules for this specific adjustment are as follows:

Setup

We have a quantity group promotion on t-shirts. If a user orders 3 t-shirts, they get $5 off of each. The shirts come in one size and three colours: red, blue, and white.

Scenario 1

User has 2 red shirts, 1 white shirt, and 1 blue shirt in their order. We want to compute the adjustment amount for the white shirt.

Result: -$5

Reasoning: There are a total of 4 items that are eligible for the promotion. Since that is greater than 3, we can discount the items. The white shirt has a quantity of 1, therefore it will get discounted by adjustment_amount * 1 or $5.

Scenario 1-1

What about the blue shirt? How much does it get discounted?

Result: $0

Reasoning: We have a total quantity of 4. However, we only apply the adjustment to groups of 3. Assuming the white and red shirts have already had their adjustment calculated, that means 3 units have been discounted. Leaving us with a lonely blue shirt that isn't part of a group of 3. Therefore, it does not receive the discount.

Scenario 2

User has 4 red shirts in their order. What is the amount?

Result: -$15

Reasoning: The total quantity of eligible items is 4, so we the adjustment will be non-zero. However, we only apply it to groups of 3, therefore there is one extra item that is not eligible for the adjustment. adjustment_amount * 3 or $15.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'app/models/spree/promotion/actions/create_quantity_adjustments.rb', line 54

def compute_amount(line_item)
  adjustment_amount = calculator.compute(PartialLineItem.new(line_item))
  if !adjustment_amount.is_a?(BigDecimal)
    Spree::Deprecation.warn "#{calculator.class.name}#compute returned #{adjustment_amount.inspect}, it should return a BigDecimal"
  end
  adjustment_amount ||= BigDecimal.new(0)
  adjustment_amount = adjustment_amount.abs

  order = line_item.order
  line_items = actionable_line_items(order)

  actioned_line_items = order.line_item_adjustments.reload.
    select { |a| a.source == self && a.amount < 0 }.
    map(&:adjustable)
  other_line_items = actioned_line_items - [line_item]

  applicable_quantity = total_applicable_quantity(line_items)
  used_quantity = total_used_quantity(other_line_items)
  usable_quantity = [
    applicable_quantity - used_quantity,
    line_item.quantity
  ].min

  persist_quantity(usable_quantity, line_item)

  amount = adjustment_amount * usable_quantity
  [line_item.amount, amount].min * -1
end