Skip to content

Commit 57e8ef9

Browse files
authored
Merge pull request #6378 from mamhoff/remove-benefit-modules
Remove benefit "level" mixins
2 parents f882e10 + a0ab878 commit 57e8ef9

File tree

12 files changed

+328
-38
lines changed

12 files changed

+328
-38
lines changed

promotions/app/models/concerns/solidus_promotions/benefits/line_item_benefit.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
module SolidusPromotions
44
module Benefits
55
module LineItemBenefit
6+
def self.included(_base)
7+
Spree.deprecator.warn("Including #{name} is deprecated.")
8+
end
9+
610
def can_discount?(object)
711
object.is_a? Spree::LineItem
812
end

promotions/app/models/concerns/solidus_promotions/benefits/order_benefit.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
module SolidusPromotions
44
module Benefits
55
module OrderBenefit
6+
def self.included(_base)
7+
Spree.deprecator.warn("Including #{name} is deprecated.")
8+
end
9+
610
def can_discount?(_)
711
false
812
end

promotions/app/models/concerns/solidus_promotions/benefits/shipment_benefit.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
module SolidusPromotions
44
module Benefits
55
module ShipmentBenefit
6+
def self.included(_base)
7+
Spree.deprecator.warn("Including #{name} is deprecated.")
8+
end
9+
610
def can_discount?(object)
711
object.is_a?(Spree::Shipment) || object.is_a?(Spree::ShippingRate)
812
end

promotions/app/models/solidus_promotions/benefit.rb

Lines changed: 65 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ module SolidusPromotions
1111
# Subclasses specialize the discounting target (orders, line items, or
1212
# shipments) and usually include one of the following mixins to integrate with
1313
# Solidus' adjustment system:
14-
# - SolidusPromotions::Benefits::OrderBenefit
15-
# - SolidusPromotions::Benefits::LineItemBenefit
16-
# - SolidusPromotions::Benefits::ShipmentBenefit
14+
# - SolidusPromotions::Benefits::AdjustLineItem
15+
# - SolidusPromotions::Benefits::AdjustShipment
16+
# - SolidusPromotions::Benefits::CreateDiscountedItem
1717
#
1818
# A benefit can discount any object for which {#can_discount?} returns true.
1919
# Implementors must provide a calculator via Spree::CalculatedAdjustments and
@@ -67,7 +67,7 @@ class Benefit < Spree::Base
6767
# Returns relations that should be preloaded for this condition.
6868
#
6969
# Override this method in subclasses to specify associations that should be eager loaded
70-
# to avoid N+1 queries when evaluating conditions.
70+
# to avoid N+1 queries when computing discounts or performing automations.
7171
#
7272
# @return [Array<Symbol>] An array of association names to preload
7373
def preload_relations
@@ -81,13 +81,11 @@ def preload_relations
8181
#
8282
# @param object [Object] a potential adjustable (order, line item, or shipment)
8383
# @return [Boolean]
84-
# @raise [NotImplementedError] when not implemented by the subclass/mixin
85-
# @see SolidusPromotions::Benefits::OrderBenefit,
86-
# SolidusPromotions::Benefits::LineItemBenefit,
87-
# SolidusPromotions::Benefits::ShipmentBenefit
84+
# @see SolidusPromotions::Benefits::AdjustLineItem,
85+
# SolidusPromotions::Benefits::AdjustShipment,
86+
# SolidusPromotions::Benefits::CreateDiscountedItem
8887
def can_discount?(object)
89-
raise NotImplementedError, "Please implement the correct interface, or include one of the `SolidusPromotions::Benefits::OrderBenefit`, " \
90-
"`SolidusPromotions::Benefits::LineItemBenefit` or `SolidusPromotions::Benefits::ShipmentBenefit` modules"
88+
respond_to?(discount_method_for(object))
9189
end
9290

9391
# Calculates and returns a discount for the given adjustable object.
@@ -96,7 +94,7 @@ def can_discount?(object)
9694
# an ItemDiscount object representing the discount to be applied. If the computed
9795
# amount is zero, no discount is returned.
9896
#
99-
# @param adjustable [Object] The object to calculate the discount for (e.g., LineItem, Order, Shipment)
97+
# @param adjustable [Object] The object to calculate the discount for (e.g., LineItem, Shipment, ShippingRate)
10098
# @param ... [args, kwargs] Additional arguments passed to the calculator's compute method
10199
#
102100
# @return [SolidusPromotions::ItemDiscount, nil] An ItemDiscount object if a discount applies, nil if the amount is zero
@@ -108,14 +106,58 @@ def can_discount?(object)
108106
# @see #compute_amount
109107
# @see #adjustment_label
110108
def discount(adjustable, ...)
111-
amount = compute_amount(adjustable, ...)
112-
return if amount.zero?
113-
ItemDiscount.new(
114-
item: adjustable,
115-
label: adjustment_label(adjustable),
116-
amount: amount,
117-
source: self
118-
)
109+
if can_discount?(adjustable)
110+
send(discount_method_for(adjustable), adjustable, ...)
111+
else
112+
raise NotImplementedError, "Please implement #{discount_method_for(adjustable)} in your condition"
113+
end
114+
end
115+
116+
def self.inherited(klass)
117+
def klass.method_added(method_added)
118+
if method_added == :discount
119+
Spree.deprecator.warn <<~MSG
120+
Please refactor `#{name}`. You're defining `#discount`. Instead, define a method for each type of discountable
121+
that your benefit can discount. For example:
122+
```
123+
class MyBenefit < SolidusPromotions::Benefit
124+
def can_discount?(discountable)
125+
discountable.is_a?(Spree::LineItem)
126+
end
127+
128+
def discount(order, _options = {})
129+
amount = compute_amount(line_item, ...)
130+
return if amount.zero?
131+
132+
ItemDiscount.new(
133+
item: line_item,
134+
label: adjustment_label(line_item),
135+
amount: amount,
136+
source: self
137+
)
138+
end
139+
```
140+
can now become
141+
```
142+
class MyBenefit < SolidusPromotions::Benefit
143+
def discount_line_item(order, ...)
144+
amount = compute_amount(line_item, ...)
145+
return if amount.zero?
146+
147+
ItemDiscount.new(
148+
item: line_item,
149+
label: adjustment_label(line_item),
150+
amount: amount,
151+
source: self
152+
)
153+
end
154+
end
155+
```
156+
MSG
157+
end
158+
super
159+
end
160+
super
119161
end
120162

121163
# Computes the discount amount for the given adjustable.
@@ -231,6 +273,10 @@ def possible_conditions
231273

232274
private
233275

276+
def discount_method_for(adjustable)
277+
:"discount_#{adjustable.class.name.demodulize.underscore}"
278+
end
279+
234280
# Prevents destroying a benefit when it has adjustments on completed orders.
235281
#
236282
# Adds an error and aborts the destroy callback chain when such adjustments exist.

promotions/app/models/solidus_promotions/benefits/adjust_line_item.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,26 @@
33
module SolidusPromotions
44
module Benefits
55
class AdjustLineItem < Benefit
6-
include SolidusPromotions::Benefits::LineItemBenefit
6+
def discount_line_item(line_item, ...)
7+
amount = compute_amount(line_item, ...)
8+
return if amount.zero?
9+
10+
ItemDiscount.new(
11+
item: line_item,
12+
label: adjustment_label(line_item),
13+
amount: amount,
14+
source: self
15+
)
16+
end
717

818
def possible_conditions
919
super + SolidusPromotions.config.line_item_conditions
1020
end
21+
22+
def level
23+
:line_item
24+
end
25+
deprecate :level, deprecator: Spree.deprecator
1126
end
1227
end
1328
end

promotions/app/models/solidus_promotions/benefits/adjust_shipment.rb

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,38 @@
33
module SolidusPromotions
44
module Benefits
55
class AdjustShipment < Benefit
6-
include SolidusPromotions::Benefits::ShipmentBenefit
6+
def discount_shipment(shipment, ...)
7+
amount = compute_amount(shipment, ...)
8+
return if amount.zero?
9+
10+
ItemDiscount.new(
11+
item: shipment,
12+
label: adjustment_label(shipment),
13+
amount: amount,
14+
source: self
15+
)
16+
end
17+
18+
def discount_shipping_rate(shipping_rate, ...)
19+
amount = compute_amount(shipping_rate, ...)
20+
return if amount.zero?
21+
22+
ItemDiscount.new(
23+
item: shipping_rate,
24+
label: adjustment_label(shipping_rate),
25+
amount: amount,
26+
source: self
27+
)
28+
end
729

830
def possible_conditions
931
super + SolidusPromotions.config.shipment_conditions
1032
end
33+
34+
def level
35+
:shipment
36+
end
37+
deprecate :level, deprecator: Spree.deprecator
1138
end
1239
end
1340
end

promotions/app/models/solidus_promotions/benefits/create_discounted_item.rb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,39 @@
33
module SolidusPromotions
44
module Benefits
55
class CreateDiscountedItem < Benefit
6-
include OrderBenefit
76
preference :variant_id, :integer
87
preference :quantity, :integer, default: 1
98
preference :necessary_quantity, :integer, default: 1
109

1110
def perform(order)
1211
line_item = find_item(order) || build_item(order)
1312
set_quantity(line_item, determine_item_quantity(order))
14-
line_item.current_discounts << discount(line_item)
13+
line_item.current_discounts << discount_line_item(line_item)
1514
end
1615

1716
def remove_from(order)
1817
find_item(order)&.mark_for_destruction
1918
end
2019

20+
def level
21+
:order
22+
end
23+
deprecate :level, deprecator: Spree.deprecator
24+
2125
private
2226

27+
def discount_line_item(line_item, ...)
28+
amount = compute_amount(line_item, ...)
29+
return if amount.zero?
30+
31+
ItemDiscount.new(
32+
item: line_item,
33+
label: adjustment_label(line_item),
34+
amount: amount,
35+
source: self
36+
)
37+
end
38+
2339
def find_item(order)
2440
order.line_items.detect { |line_item| line_item.managed_by_order_benefit == self }
2541
end

0 commit comments

Comments
 (0)