Skip to content

Commit 0b90bc5

Browse files
committed
Add YARD docs to TieredPercentOnEligibleItemQuantity calculator
This really helps to understand what this does.
1 parent 5319913 commit 0b90bc5

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

promotions/app/models/solidus_promotions/calculators/tiered_percent_on_eligible_item_quantity.rb

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,43 @@
44

55
module SolidusPromotions
66
module Calculators
7+
# A calculator that applies tiered percentage discounts based on the total quantity of eligible items.
8+
#
9+
# This calculator defines discount tiers based on the combined quantity of all eligible line items
10+
# in an order (not their monetary value). Each tier specifies a minimum quantity threshold and the
11+
# corresponding percentage discount to apply. The calculator selects the highest tier that the
12+
# order's eligible item quantity meets or exceeds.
13+
#
14+
# The tier thresholds are evaluated against the total quantity of eligible line items, but the
15+
# percentage discount is applied to each individual item's discountable amount. This makes it
16+
# ideal for "buy more, save more" promotions based on item count rather than order value.
17+
#
18+
# If the total eligible quantity doesn't meet any tier threshold, the base percentage is used.
19+
# The discount is only applied if the currency matches the preferred currency.
20+
#
21+
# @example Use case: Bulk quantity discounts
22+
# # Buy 10+ items get 5% off, 25+ get 10% off, 50+ get 15% off
23+
# calculator = TieredPercentOnEligibleItemQuantity.new(
24+
# preferred_base_percent: 0,
25+
# preferred_tiers: {
26+
# 10 => 5, # 5% off when total eligible quantity >= 10
27+
# 25 => 10, # 10% off when total eligible quantity >= 25
28+
# 50 => 15 # 15% off when total eligible quantity >= 50
29+
# },
30+
# preferred_currency: 'USD'
31+
# )
32+
#
33+
# @example Use case: Multi-item bundle promotions
34+
# # Encourage buying multiple items from a category
35+
# calculator = TieredPercentOnEligibleItemQuantity.new(
36+
# preferred_base_percent: 0,
37+
# preferred_tiers: {
38+
# 3 => 10, # 10% off when buying 3+ eligible items
39+
# 5 => 15, # 15% off when buying 5+ eligible items
40+
# 10 => 20 # 20% off when buying 10+ eligible items
41+
# },
42+
# preferred_currency: 'USD'
43+
# )
744
class TieredPercentOnEligibleItemQuantity < Spree::Calculator
845
include PromotionCalculator
946

@@ -13,6 +50,42 @@ class TieredPercentOnEligibleItemQuantity < Spree::Calculator
1350

1451
before_validation :transform_preferred_tiers
1552

53+
# Computes the tiered percentage discount for an item based on total eligible item quantity.
54+
#
55+
# Evaluates the total quantity of all eligible line items in the order against all defined
56+
# tiers and selects the highest tier threshold that is met or exceeded. Returns a percentage
57+
# of the item's discountable amount based on the matching tier, or the base percentage if no
58+
# tier threshold is met. Returns 0 if the currency doesn't match.
59+
#
60+
# @param item [Object] The object to calculate the discount for (e.g., LineItem, Shipment, ShippingRate)
61+
#
62+
# @return [BigDecimal] The percentage-based discount amount, rounded to currency precision
63+
#
64+
# @example Computing discount with tier matching
65+
# calculator = TieredPercentOnEligibleItemQuantity.new(
66+
# preferred_base_percent: 0,
67+
# preferred_tiers: { 10 => 10, 25 => 15 }
68+
# )
69+
# # Order has 3 eligible line items with quantities: 5, 6, 4 (total: 15)
70+
# line_item.discountable_amount # => 50.00
71+
# calculator.compute_item(line_item) # => 5.00 (10% of $50, matches quantity tier of 10)
72+
#
73+
# @example Computing discount below all tiers
74+
# calculator = TieredPercentOnEligibleItemQuantity.new(
75+
# preferred_base_percent: 5,
76+
# preferred_tiers: { 10 => 10, 25 => 15 }
77+
# )
78+
# # Order has 2 eligible line items with quantities: 3, 4 (total: 7)
79+
# line_item.discountable_amount # => 30.00
80+
# calculator.compute_item(line_item) # => 1.50 (5% base percent of $30)
81+
#
82+
# @example Computing discount with currency mismatch
83+
# calculator = TieredPercentOnEligibleItemQuantity.new(
84+
# preferred_currency: 'USD',
85+
# preferred_tiers: { 10 => 10 }
86+
# )
87+
# order.currency # => 'EUR'
88+
# calculator.compute_item(line_item) # => 0
1689
def compute_item(item)
1790
order = item.order
1891

@@ -31,13 +104,21 @@ def compute_item(item)
31104

32105
private
33106

107+
# Transforms preferred_tiers keys to integers and values to BigDecimal.
108+
#
109+
# Converts tier threshold keys (item quantities) to integers and percentage values
110+
# to BigDecimal for consistent calculations.
34111
def transform_preferred_tiers
35112
return unless preferred_tiers.is_a?(Hash)
36113

37114
preferred_tiers.transform_keys!(&:to_i)
38115
preferred_tiers.transform_values! { |value| value.to_s.to_d }
39116
end
40117

118+
# Calculates the total quantity of all eligible line items in the order.
119+
#
120+
# @param order [Spree::Order] The order to calculate eligible quantity for
121+
# @return [Integer] The sum of quantities for all applicable line items
41122
def eligible_line_items_quantity_total(order)
42123
calculable.applicable_line_items(order).sum(&:quantity)
43124
end

0 commit comments

Comments
 (0)