@@ -4,7 +4,7 @@ class Order
4
4
5
5
def initialize ( id )
6
6
@id = id
7
- @product_quantity_hash = Hash . new ( 0 )
7
+ @list = List . new
8
8
@discount = Discounts ::NoPercentageDiscount . new
9
9
end
10
10
@@ -56,7 +56,7 @@ def reset_discount
56
56
end
57
57
58
58
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?
60
60
apply ProductMadeFreeForOrder . new (
61
61
data : {
62
62
order_id : order_id ,
@@ -66,7 +66,7 @@ def make_product_free(order_id, product_id)
66
66
end
67
67
68
68
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?
70
70
apply FreeProductRemovedFromOrder . new (
71
71
data : {
72
72
order_id : order_id ,
@@ -76,7 +76,7 @@ def remove_free_product(order_id, product_id)
76
76
end
77
77
78
78
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 )
80
80
81
81
discounted_value = @discount . add ( time_promotion_discount ) . apply ( total_value )
82
82
apply (
@@ -91,13 +91,11 @@ def calculate_total_value(pricing_catalog, time_promotion_discount)
91
91
end
92
92
93
93
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 )
97
95
sub_discounts = calculate_total_sub_discounts ( pricing_catalog , time_promotions_discount )
98
96
99
- products = @product_quantity_hash . keys
100
- quantities = @product_quantity_hash . values
97
+ products = @list . products
98
+ quantities = @list . quantities
101
99
products . zip ( quantities , sub_amounts_total , sub_discounts ) do |product , quantity , sub_amount , sub_discount |
102
100
apply (
103
101
PriceItemValueCalculated . new (
@@ -116,20 +114,11 @@ def calculate_sub_amounts(pricing_catalog, time_promotions_discount)
116
114
private
117
115
118
116
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 ) ) )
120
118
end
121
119
122
120
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 ) )
133
122
end
134
123
135
124
on PriceItemValueCalculated do |event |
@@ -151,26 +140,69 @@ def clear_empty_products
151
140
end
152
141
153
142
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 ) )
156
144
end
157
145
158
146
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 ) )
161
148
end
162
149
163
150
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 )
169
152
end
170
153
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
174
206
end
175
207
176
208
class Product
0 commit comments