Skip to content

remove calculate total offer from offer aggregate 2 #452

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 73 additions & 4 deletions ecommerce/pricing/lib/pricing/calculate_order_total_value.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,83 @@
module Pricing
class CalculateOrderTotalValue
def call(event)
command_bus.(CalculateTotalValue.new(order_id: event.data.fetch(:order_id)))
items = []
discounts = []
events =
event_store
.read
.stream("Pricing::Offer$#{event.data.fetch(:order_id)}")
.to_a
events.each do |event|
case event
when PriceItemAdded
items << {
product_id: event.data.fetch(:product_id),
base_price: event.data.fetch(:base_price),
price: event.data.fetch(:base_price)
}
when PriceItemRemoved
index =
items.index do |i|
i[:product_id] == event.data[:product_id] &&
i[:price] == event.data[:price]
end
items.delete_at(index) if index
when PercentageDiscountSet
discounts << {
type: event.data.fetch(:type),
amount: event.data.fetch(:amount)
}
when PercentageDiscountChanged
discounts =
discounts.reject do |discount|
discount[:type] == event.data.fetch(:type)
end
discounts << {
type: event.data.fetch(:type),
amount: event.data.fetch(:amount)
}
when PercentageDiscountRemoved
discounts =
discounts.reject do |discount|
discount[:type] == event.data.fetch(:type)
end
when ProductMadeFreeForOrder
item =
items.find do |i|
i[:product_id] == event.data.fetch(:product_id) && i[:price] > 0
end
item[:price] = 0.0 if item
when FreeProductRemovedFromOrder
item =
items.find do |i|
i[:product_id] == event.data.fetch(:product_id) && i[:price] == 0
end
item[:price] = item[:base_price] if item
end
end

total_amount = items.sum { |item| item[:base_price] }
discounted_amount = items.sum { |item| item[:price] }
discounts.each do |discount|
discounted_amount -= discounted_amount * (discount[:amount] / 100)
end

event_store.publish(
OrderTotalValueCalculated.new(
data: {
order_id: event.data.fetch(:order_id),
total_amount:,
discounted_amount:
}
)
)
end

private

def command_bus
Pricing.command_bus
def event_store
Pricing.event_store
end
end
end

205 changes: 121 additions & 84 deletions ecommerce/pricing/test/free_products_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,26 @@ def test_making_product_free_possible_when_order_is_eligible
add_item(order_id, product_1_id)
add_item(order_id, product_1_id)

assert_events_contain(
stream_name(order_id),
ProductMadeFreeForOrder.new(
data: {
order_id: order_id,
product_id: product_1_id
}
),
OrderTotalValueCalculated.new(
data: {
order_id: order_id,
discounted_amount: 60,
total_amount: 80
}
)
assert_published_within(
OrderTotalValueCalculated,
{ order_id: order_id, discounted_amount: 60, total_amount: 80 }
) do
run_command(
Pricing::MakeProductFreeForOrder.new(order_id: order_id, product_id: product_1_id)
)
assert_events_contain(
stream_name(order_id),
ProductMadeFreeForOrder.new(
data: {
order_id: order_id,
product_id: product_1_id
}
)
) do
run_command(
Pricing::MakeProductFreeForOrder.new(
order_id: order_id,
product_id: product_1_id
)
)
end
end
end

Expand All @@ -46,25 +47,26 @@ def test_making_only_the_cheapest_product_free
add_item(order_id, product_1_id)
add_item(order_id, cheaper_product)

assert_events_contain(
stream_name(order_id),
ProductMadeFreeForOrder.new(
data: {
order_id: order_id,
product_id: cheaper_product
}
),
OrderTotalValueCalculated.new(
data: {
order_id: order_id,
discounted_amount: 60,
total_amount: 70
}
),
assert_published_within(
OrderTotalValueCalculated,
{ order_id: order_id, discounted_amount: 60, total_amount: 70 }
) do
run_command(
Pricing::MakeProductFreeForOrder.new(order_id: order_id, product_id: cheaper_product)
)
assert_events_contain(
stream_name(order_id),
ProductMadeFreeForOrder.new(
data: {
order_id: order_id,
product_id: cheaper_product
}
)
) do
run_command(
Pricing::MakeProductFreeForOrder.new(
order_id: order_id,
product_id: cheaper_product
)
)
end
end
end

Expand All @@ -78,12 +80,18 @@ def test_making_product_free_not_possible_if_is_already_set
add_item(order_id, product_1_id)

run_command(
Pricing::MakeProductFreeForOrder.new(order_id: order_id, product_id: product_1_id)
Pricing::MakeProductFreeForOrder.new(
order_id: order_id,
product_id: product_1_id
)
)

assert_raises FreeProductAlreadyMade do
run_command(
Pricing::MakeProductFreeForOrder.new(order_id: order_id, product_id: product_1_id)
Pricing::MakeProductFreeForOrder.new(
order_id: order_id,
product_id: product_1_id
)
)
end
end
Expand All @@ -98,40 +106,54 @@ def test_making_product_free_possible_after_previous_free_product_was_removed
add_item(order_id, product_1_id)

run_command(
Pricing::MakeProductFreeForOrder.new(order_id: order_id, product_id: product_1_id)
Pricing::MakeProductFreeForOrder.new(
order_id: order_id,
product_id: product_1_id
)
)

run_command(
Pricing::RemovePriceItem.new(order_id: order_id, product_id: product_1_id)
Pricing::RemovePriceItem.new(
order_id: order_id,
product_id: product_1_id
)
)

run_command(
Pricing::RemoveFreeProductFromOrder.new(order_id: order_id, product_id: product_1_id)
Pricing::RemoveFreeProductFromOrder.new(
order_id: order_id,
product_id: product_1_id
)
)

run_command(
Pricing::AddPriceItem.new(order_id: order_id, product_id: product_1_id, price: 20)
Pricing::AddPriceItem.new(
order_id: order_id,
product_id: product_1_id,
price: 20
)
)

assert_events_contain(
stream_name(order_id),
ProductMadeFreeForOrder.new(
data: {
order_id: order_id,
product_id: product_1_id
}
),
OrderTotalValueCalculated.new(
data: {
order_id: order_id,
discounted_amount: 60,
total_amount: 80
}
)
assert_published_within(
OrderTotalValueCalculated,
{ order_id: order_id, discounted_amount: 60, total_amount: 80 }
) do
run_command(
Pricing::MakeProductFreeForOrder.new(order_id: order_id, product_id: product_1_id)
)
assert_events_contain(
stream_name(order_id),
ProductMadeFreeForOrder.new(
data: {
order_id: order_id,
product_id: product_1_id
}
),
) do
run_command(
Pricing::MakeProductFreeForOrder.new(
order_id: order_id,
product_id: product_1_id
)
)
end
end
end

Expand All @@ -145,28 +167,32 @@ def test_removing_free_product_possible_if_it_is_already_set
add_item(order_id, product_1_id)

run_command(
Pricing::MakeProductFreeForOrder.new(order_id: order_id, product_id: product_1_id)
Pricing::MakeProductFreeForOrder.new(
order_id: order_id,
product_id: product_1_id
)
)

assert_events_contain(
stream_name(order_id),
FreeProductRemovedFromOrder.new(
data: {
order_id: order_id,
product_id: product_1_id
}
),
OrderTotalValueCalculated.new(
data: {
order_id: order_id,
discounted_amount: 80,
total_amount: 80
}
)
assert_published_within(
OrderTotalValueCalculated,
{ order_id: order_id, discounted_amount: 80, total_amount: 80 }
) do
run_command(
Pricing::RemoveFreeProductFromOrder.new(order_id: order_id, product_id: product_1_id)
)
assert_events_contain(
stream_name(order_id),
FreeProductRemovedFromOrder.new(
data: {
order_id: order_id,
product_id: product_1_id
}
)
) do
run_command(
Pricing::RemoveFreeProductFromOrder.new(
order_id: order_id,
product_id: product_1_id
)
)
end
end
end

Expand All @@ -178,7 +204,10 @@ def test_removing_free_product_not_possible_if_is_not_set

assert_no_events(stream_name(order_id)) do
run_command(
Pricing::RemoveFreeProductFromOrder.new(order_id: order_id, product_id: product_1_id)
Pricing::RemoveFreeProductFromOrder.new(
order_id: order_id,
product_id: product_1_id
)
)
end
end
Expand All @@ -193,16 +222,25 @@ def test_removing_free_product_twice_not_possible
add_item(order_id, product_1_id)

run_command(
Pricing::MakeProductFreeForOrder.new(order_id: order_id, product_id: product_1_id)
Pricing::MakeProductFreeForOrder.new(
order_id: order_id,
product_id: product_1_id
)
)

run_command(
Pricing::RemoveFreeProductFromOrder.new(order_id: order_id, product_id: product_1_id)
Pricing::RemoveFreeProductFromOrder.new(
order_id: order_id,
product_id: product_1_id
)
)

assert_no_events(stream_name(order_id)) do
run_command(
Pricing::RemoveFreeProductFromOrder.new(order_id: order_id, product_id: product_1_id)
Pricing::RemoveFreeProductFromOrder.new(
order_id: order_id,
product_id: product_1_id
)
)
end
end
Expand All @@ -212,6 +250,5 @@ def test_removing_free_product_twice_not_possible
def stream_name(id)
"Pricing::Offer$#{id}"
end

end
end
Loading
Loading