Skip to content

Commit 723f21e

Browse files
Extracted List class from Order aggregate
It used to be a Hash primitive. After extracting we have better method names and the Order aggregate became smaller.
1 parent 22a95e7 commit 723f21e

File tree

1 file changed

+64
-32
lines changed

1 file changed

+64
-32
lines changed

ecommerce/pricing/lib/pricing/order.rb

+64-32
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class Order
44

55
def initialize(id)
66
@id = id
7-
@product_quantity_hash = Hash.new(0)
7+
@list = List.new
88
@discount = Discounts::NoPercentageDiscount.new
99
end
1010

@@ -56,7 +56,7 @@ def reset_discount
5656
end
5757

5858
def make_product_free(order_id, product_id)
59-
raise FreeProductAlreadyMade if @product_quantity_hash.keys.any? {|key| key.instance_of?(FreeProduct)}
59+
raise FreeProductAlreadyMade if @list.contains_free_products?
6060
apply ProductMadeFreeForOrder.new(
6161
data: {
6262
order_id: order_id,
@@ -66,7 +66,7 @@ def make_product_free(order_id, product_id)
6666
end
6767

6868
def remove_free_product(order_id, product_id)
69-
raise FreeProductNotExists if @product_quantity_hash.keys.none? {|key| key.instance_of?(FreeProduct)}
69+
raise FreeProductNotExists unless @list.contains_free_products?
7070
apply FreeProductRemovedFromOrder.new(
7171
data: {
7272
order_id: order_id,
@@ -76,7 +76,7 @@ def remove_free_product(order_id, product_id)
7676
end
7777

7878
def calculate_total_value(pricing_catalog, time_promotion_discount)
79-
total_value = @product_quantity_hash.sum { |product, qty| pricing_catalog.price_for(product) * qty }
79+
total_value = @list.base_sum(pricing_catalog)
8080

8181
discounted_value = @discount.add(time_promotion_discount).apply(total_value)
8282
apply(
@@ -91,13 +91,11 @@ def calculate_total_value(pricing_catalog, time_promotion_discount)
9191
end
9292

9393
def calculate_sub_amounts(pricing_catalog, time_promotions_discount)
94-
sub_amounts_total = @product_quantity_hash.map do |product, quantity|
95-
quantity * pricing_catalog.price_for(product)
96-
end
94+
sub_amounts_total = @list.sub_amounts_total(pricing_catalog)
9795
sub_discounts = calculate_total_sub_discounts(pricing_catalog, time_promotions_discount)
9896

99-
products = @product_quantity_hash.keys
100-
quantities = @product_quantity_hash.values
97+
products = @list.products
98+
quantities = @list.quantities
10199
products.zip(quantities, sub_amounts_total, sub_discounts) do |product, quantity, sub_amount, sub_discount|
102100
apply(
103101
PriceItemValueCalculated.new(
@@ -116,20 +114,11 @@ def calculate_sub_amounts(pricing_catalog, time_promotions_discount)
116114
private
117115

118116
on PriceItemAdded do |event|
119-
@product_quantity_hash[Product.new(event.data.fetch(:product_id))] += 1
117+
@list.add_item(Product.new(event.data.fetch(:product_id)))
120118
end
121119

122120
on PriceItemRemoved do |event|
123-
if @product_quantity_hash[Product.new(event.data.fetch(:product_id))]
124-
@product_quantity_hash[Product.new(event.data.fetch(:product_id))] -= 1
125-
else
126-
@product_quantity_hash[FreeProduct.new(event.data.fetch(:product_id))] -= 1
127-
end
128-
clear_empty_products
129-
end
130-
131-
def clear_empty_products
132-
@product_quantity_hash.delete_if { |_, value| value.zero? }
121+
@list.remove_item(event.data.fetch(:product_id))
133122
end
134123

135124
on PriceItemValueCalculated do |event|
@@ -151,26 +140,69 @@ def clear_empty_products
151140
end
152141

153142
on ProductMadeFreeForOrder do |event|
154-
replace(Product, FreeProduct, event.data.fetch(:product_id))
155-
clear_empty_products
143+
@list.replace(Product, FreeProduct, event.data.fetch(:product_id))
156144
end
157145

158146
on FreeProductRemovedFromOrder do |event|
159-
replace(FreeProduct, Product, event.data.fetch(:product_id))
160-
clear_empty_products
147+
@list.replace(FreeProduct, Product, event.data.fetch(:product_id))
161148
end
162149

163150
def calculate_total_sub_discounts(pricing_catalog, time_promotions_discount)
164-
@product_quantity_hash.map do |product, quantity|
165-
catalog_price_for_single = pricing_catalog.price_for(product)
166-
with_total_discount_single = @discount.add(time_promotions_discount).apply(catalog_price_for_single)
167-
quantity * (catalog_price_for_single - with_total_discount_single)
168-
end
151+
@list.sub_discounts(pricing_catalog, time_promotions_discount, @discount)
169152
end
170153

171-
def replace(from, to, product_id)
172-
@product_quantity_hash[from.new(product_id)] -= 1
173-
@product_quantity_hash[to.new(product_id)] += 1
154+
class List
155+
156+
def initialize
157+
@products_quantities = Hash.new(0)
158+
end
159+
160+
def add_item(product)
161+
@products_quantities[product] += 1
162+
end
163+
164+
def remove_item(product_id)
165+
@products_quantities[Product.new(product_id)] -= 1
166+
clear_empty_products
167+
end
168+
169+
def clear_empty_products
170+
@products_quantities.delete_if { |_, value| value.zero? }
171+
end
172+
173+
def replace(from, to, product_id)
174+
@products_quantities[from.new(product_id)] -= 1
175+
@products_quantities[to.new(product_id)] += 1
176+
clear_empty_products
177+
end
178+
179+
def products
180+
@products_quantities.keys
181+
end
182+
183+
def quantities
184+
@products_quantities.values
185+
end
186+
187+
def contains_free_products?
188+
@products_quantities.keys.any? {|key| key.instance_of?(FreeProduct) }
189+
end
190+
191+
def base_sum(pricing_catalog)
192+
@products_quantities.sum { |product, qty| pricing_catalog.price_for(product) * qty }
193+
end
194+
195+
def sub_amounts_total(pricing_catalog)
196+
@products_quantities.map { |product, quantity| quantity * pricing_catalog.price_for(product) }
197+
end
198+
199+
def sub_discounts(pricing_catalog, time_promotions_discount, discount)
200+
@products_quantities.map do |product, quantity|
201+
catalog_price_for_single = pricing_catalog.price_for(product)
202+
with_total_discount_single = discount.add(time_promotions_discount).apply(catalog_price_for_single)
203+
quantity * (catalog_price_for_single - with_total_discount_single)
204+
end
205+
end
174206
end
175207

176208
class Product

0 commit comments

Comments
 (0)