Skip to content

Commit 8c08418

Browse files
Move more InvoiceGeneration logic to the Invoice data class
This way the main process is more clear at the high level.
1 parent 253b767 commit 8c08418

File tree

1 file changed

+57
-36
lines changed

1 file changed

+57
-36
lines changed

rails_application/app/processes/processes/invoice_generation.rb

Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -74,53 +74,27 @@ def create_invoice_items_for_product(product_id, quantity, discounted_amount)
7474
end
7575

7676
def apply_price_item_added(product_id, base_price, price)
77-
lines = (state.lines + [{ product_id:, base_price:, price: }])
78-
state.with(lines:)
77+
state.add_line(product_id, base_price, price)
7978
end
8079

8180
def apply_price_item_removed(product_id)
82-
lines = state.lines.dup
83-
index_to_remove = lines.find_index { |line| line.fetch(:product_id) == product_id}
84-
lines.delete_at(index_to_remove)
85-
state.with(lines:)
81+
state.remove_line(product_id)
8682
end
8783

8884
def apply_percentage_discount_set(discount_type, discount_amount)
89-
discounts = state.discounts.reject { |d| d.fetch(:type) == discount_type }
90-
discounts = discounts + [{ type: discount_type, amount: discount_amount }]
91-
new_state = state.with(discounts:)
92-
apply_discounts_to_existing_lines(new_state)
85+
state.set_discount(discount_type, discount_amount)
9386
end
9487

9588
def apply_percentage_discount_changed(discount_type, discount_amount)
96-
discounts = state.discounts.reject { |d| d.fetch(:type) == discount_type }
97-
discounts = discounts + [{ amount: discount_amount }]
98-
new_state = state.with(discounts: discounts)
99-
apply_discounts_to_existing_lines(new_state)
89+
state.set_discount(discount_type, discount_amount)
10090
end
10191

10292
def apply_percentage_discount_removed(discount_type)
103-
discounts = state.discounts.reject { |d| d.fetch(:type) == discount_type }
104-
new_state = state.with(discounts:)
105-
apply_discounts_to_existing_lines(new_state)
106-
end
107-
108-
def apply_discounts_to_existing_lines(new_state)
109-
total_discount_percentage = new_state.total_discount_percentage
110-
final_discount_percentage = [total_discount_percentage, 100].min
111-
discount_multiplier = (1 - final_discount_percentage / 100.0)
112-
113-
updated_lines = new_state.lines.map do |line|
114-
base_price = line.fetch(:base_price)
115-
discounted_price = base_price * discount_multiplier
116-
line.merge(price: discounted_price)
117-
end
118-
119-
new_state.with(lines: updated_lines)
93+
state.remove_discount(discount_type)
12094
end
12195

12296
def apply_order_registered
123-
state.with(order_placed: true)
97+
state.mark_placed
12498
end
12599

126100
end
@@ -130,6 +104,50 @@ def initialize(lines: [], discounts: [], order_placed: false)
130104
super(lines: lines.freeze, discounts: discounts.freeze, order_placed: order_placed)
131105
end
132106

107+
def add_line(product_id, base_price, price)
108+
with(lines: lines + [{ product_id:, base_price:, price: }])
109+
end
110+
111+
def remove_line(product_id)
112+
new_lines = lines.dup
113+
index = new_lines.find_index { |line| line.fetch(:product_id) == product_id }
114+
new_lines.delete_at(index)
115+
with(lines: new_lines)
116+
end
117+
118+
def set_discount(type, amount)
119+
new_discounts = discounts.reject { |d| d.fetch(:type) == type } +
120+
[{ type:, amount: }]
121+
with_discounts_applied(new_discounts)
122+
end
123+
124+
def remove_discount(type)
125+
new_discounts = discounts.reject { |d| d.fetch(:type) == type }
126+
with_discounts_applied(new_discounts)
127+
end
128+
129+
def mark_placed
130+
with(order_placed: true)
131+
end
132+
133+
def placed?
134+
order_placed
135+
end
136+
137+
def apply_discounts_to_lines
138+
total_discount_percentage = self.total_discount_percentage
139+
final_discount_percentage = [total_discount_percentage, 100].min
140+
discount_multiplier = (1 - final_discount_percentage / 100.0)
141+
142+
updated_lines = lines.map do |line|
143+
base_price = line.fetch(:base_price)
144+
discounted_price = base_price * discount_multiplier
145+
line.merge(price: discounted_price)
146+
end
147+
148+
with(lines: updated_lines)
149+
end
150+
133151
def sub_amounts_total
134152
lines.each_with_object({}) do |line, memo|
135153
product_id = line.fetch(:product_id)
@@ -140,6 +158,13 @@ def sub_amounts_total
140158
end
141159
end
142160

161+
private
162+
163+
def with_discounts_applied(new_discounts)
164+
new_state = with(discounts: new_discounts)
165+
new_state.apply_discounts_to_lines
166+
end
167+
143168
def subtotal
144169
lines.sum { |line| line.fetch(:price) }
145170
end
@@ -155,10 +180,6 @@ def final_discount_percentage
155180
def discounted_value
156181
subtotal * (1 - final_discount_percentage / 100.0)
157182
end
158-
159-
def placed?
160-
order_placed
161-
end
162183
end
163184

164185
class MoneySplitter

0 commit comments

Comments
 (0)