Skip to content

Commit

Permalink
Refactor discounts
Browse files Browse the repository at this point in the history
  • Loading branch information
marlena-b committed Nov 26, 2024
1 parent 0426d64 commit e668817
Show file tree
Hide file tree
Showing 22 changed files with 90 additions and 85 deletions.
14 changes: 7 additions & 7 deletions ecommerce/pricing/lib/pricing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ def call(event_store, command_bus)
SetPercentageDiscountHandler.new(event_store)
)
command_bus.register(
ResetPercentageDiscount,
ResetPercentageDiscountHandler.new(event_store)
RemovePercentageDiscount,
RemovePercentageDiscountHandler.new(event_store)
)
command_bus.register(
ChangePercentageDiscount,
Expand Down Expand Up @@ -96,14 +96,14 @@ def call(event_store, command_bus)
SetTimePromotionDiscountHandler.new(event_store)
)
command_bus.register(
ResetTimePromotionDiscount,
ResetTimePromotionDiscountHandler.new(event_store)
RemoveTimePromotionDiscount,
RemoveTimePromotionDiscountHandler.new(event_store)
)
event_store.subscribe(ApplyTimePromotion, to: [
PriceItemAdded,
PriceItemRemoved,
PercentageDiscountSet,
PercentageDiscountReset,
PercentageDiscountRemoved,
PercentageDiscountChanged,
ProductMadeFreeForOrder,
FreeProductRemovedFromOrder
Expand All @@ -112,7 +112,7 @@ def call(event_store, command_bus)
PriceItemAdded,
PriceItemRemoved,
PercentageDiscountSet,
PercentageDiscountReset,
PercentageDiscountRemoved,
PercentageDiscountChanged,
ProductMadeFreeForOrder,
FreeProductRemovedFromOrder
Expand All @@ -121,7 +121,7 @@ def call(event_store, command_bus)
PriceItemAdded,
PriceItemRemoved,
PercentageDiscountSet,
PercentageDiscountReset,
PercentageDiscountRemoved,
PercentageDiscountChanged,
ProductMadeFreeForOrder,
FreeProductRemovedFromOrder
Expand Down
4 changes: 2 additions & 2 deletions ecommerce/pricing/lib/pricing/apply_time_promotion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ def call(event)
if discount.exists?
command_bus.(SetTimePromotionDiscount.new(order_id: event.data.fetch(:order_id), amount: discount.value))
else
command_bus.(ResetTimePromotionDiscount.new(order_id: event.data.fetch(:order_id)))
command_bus.(RemoveTimePromotionDiscount.new(order_id: event.data.fetch(:order_id)))
end

rescue NotPossibleToAssignDiscountTwice, NotPossibleToResetWithoutDiscount
rescue NotPossibleToAssignDiscountTwice, NotPossibleToRemoveWithoutDiscount
end

private
Expand Down
4 changes: 2 additions & 2 deletions ecommerce/pricing/lib/pricing/commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SetPercentageDiscount < Infra::Command
alias aggregate_id order_id
end

class ResetPercentageDiscount < Infra::Command
class RemovePercentageDiscount < Infra::Command
attribute :order_id, Infra::Types::UUID
alias aggregate_id order_id
end
Expand All @@ -52,7 +52,7 @@ class SetTimePromotionDiscount < Infra::Command
alias aggregate_id order_id
end

class ResetTimePromotionDiscount < Infra::Command
class RemoveTimePromotionDiscount < Infra::Command
attribute :order_id, Infra::Types::UUID

alias aggregate_id order_id
Expand Down
5 changes: 3 additions & 2 deletions ecommerce/pricing/lib/pricing/discounts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ def self.build(discount)
end

class PercentageDiscount
attr_reader :value
attr_reader :value, :type

def initialize(value)
def initialize(type = GENERAL_DISCOUNT, value)
raise UnacceptableDiscountRange if value <= 0
raise UnacceptableDiscountRange if value > 100

@type = type
@value = value
end

Expand Down
2 changes: 1 addition & 1 deletion ecommerce/pricing/lib/pricing/events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class PriceItemRemoved < Infra::Event
attribute :product_id, Infra::Types::UUID
end

class PercentageDiscountReset < Infra::Event
class PercentageDiscountRemoved < Infra::Event
attribute :order_id, Infra::Types::UUID
attribute :type, Infra::Types::String
end
Expand Down
37 changes: 21 additions & 16 deletions ecommerce/pricing/lib/pricing/offer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Offer
def initialize(id)
@id = id
@list = List.new
@discounts = {}
@discounts = []
end

def add_item(product_id)
Expand All @@ -26,31 +26,31 @@ def remove_item(product_id)
)
end

def apply_discount(type, discount)
raise NotPossibleToAssignDiscountTwice if @discounts.include?(type)
def apply_discount(discount)
raise NotPossibleToAssignDiscountTwice if discount_exists?(discount.type)
apply PercentageDiscountSet.new(
data: {
order_id: @id,
type: type,
type: discount.type,
amount: discount.value
}
)
end

def change_discount(type, discount)
raise NotPossibleToChangeDiscount unless @discounts.include?(type)
def change_discount(discount)
raise NotPossibleToChangeDiscount unless discount_exists?(discount.type)
apply PercentageDiscountChanged.new(
data: {
order_id: @id,
type: type,
type: discount.type,
amount: discount.value
}
)
end

def reset_discount(type)
raise NotPossibleToResetWithoutDiscount unless @discounts.include?(type)
apply PercentageDiscountReset.new(
def remove_discount(type)
raise NotPossibleToRemoveWithoutDiscount unless discount_exists?(type)
apply PercentageDiscountRemoved.new(
data: {
order_id: @id,
type: type
Expand Down Expand Up @@ -80,7 +80,7 @@ def remove_free_product(order_id, product_id)

def calculate_total_value(pricing_catalog)
total_value = @list.base_sum(pricing_catalog)
discounted_value = @discounts.values.inject(Discounts::NoPercentageDiscount.new, :add).apply(total_value)
discounted_value = @discounts.inject(Discounts::NoPercentageDiscount.new, :add).apply(total_value)

apply(
OrderTotalValueCalculated.new(
Expand Down Expand Up @@ -141,15 +141,16 @@ def use_coupon(coupon_id, discount)
end

on PercentageDiscountSet do |event|
@discounts[event.data.fetch(:type)] = Discounts::PercentageDiscount.new(event.data.fetch(:amount))
@discounts << Discounts::PercentageDiscount.new(event.data.fetch(:type), event.data.fetch(:amount))
end

on PercentageDiscountChanged do |event|
@discounts[event.data.fetch(:type)] = Discounts::PercentageDiscount.new(event.data.fetch(:amount))
@discounts.delete_if { |discount| discount.type == event.data.fetch(:type) }
@discounts << Discounts::PercentageDiscount.new(event.data.fetch(:type), event.data.fetch(:amount))
end

on PercentageDiscountReset do |event|
@discounts.delete(event.data.fetch(:type))
on PercentageDiscountRemoved do |event|
@discounts.delete_if { |discount| discount.type == event.data.fetch(:type) }
end

on ProductMadeFreeForOrder do |event|
Expand All @@ -167,6 +168,10 @@ def calculate_total_sub_discounts(pricing_catalog)
on CouponUsed do |event|
end

def discount_exists?(type)
@discounts.find { |discount| discount.type == type }
end

class List

def initialize
Expand Down Expand Up @@ -215,7 +220,7 @@ def sub_amounts_total(pricing_catalog)
def sub_discounts(pricing_catalog, discounts)
@products_quantities.map do |product, quantity|
catalog_price_for_single = pricing_catalog.price_for(product)
with_total_discount_single = discounts.values.inject(Discounts::NoPercentageDiscount.new, :add).apply(catalog_price_for_single)
with_total_discount_single = discounts.inject(Discounts::NoPercentageDiscount.new, :add).apply(catalog_price_for_single)
quantity * (catalog_price_for_single - with_total_discount_single)
end
end
Expand Down
16 changes: 8 additions & 8 deletions ecommerce/pricing/lib/pricing/services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Pricing
class NotPossibleToAssignDiscountTwice < StandardError
end

class NotPossibleToResetWithoutDiscount < StandardError
class NotPossibleToRemoveWithoutDiscount < StandardError
end

class NotPossibleToChangeDiscount < StandardError
Expand All @@ -21,19 +21,19 @@ def initialize(event_store)

def call(cmd)
@repository.with_aggregate(Offer, cmd.aggregate_id) do |order|
order.apply_discount(Discounts::GENERAL_DISCOUNT, Discounts::PercentageDiscount.new(cmd.amount))
order.apply_discount(Discounts::PercentageDiscount.new(cmd.amount))
end
end
end

class ResetPercentageDiscountHandler
class RemovePercentageDiscountHandler
def initialize(event_store)
@repository = Infra::AggregateRootRepository.new(event_store)
end

def call(cmd)
@repository.with_aggregate(Offer, cmd.aggregate_id) do |order|
order.reset_discount(Discounts::GENERAL_DISCOUNT)
order.remove_discount(Discounts::GENERAL_DISCOUNT)
end
end
end
Expand All @@ -45,7 +45,7 @@ def initialize(event_store)

def call(cmd)
@repository.with_aggregate(Offer, cmd.aggregate_id) do |order|
order.change_discount(Discounts::GENERAL_DISCOUNT, Discounts::PercentageDiscount.new(cmd.amount))
order.change_discount(Discounts::PercentageDiscount.new(cmd.amount))
end
end
end
Expand All @@ -57,19 +57,19 @@ def initialize(event_store)

def call(cmd)
@repository.with_aggregate(Offer, cmd.aggregate_id) do |order|
order.apply_discount(Discounts::TIME_PROMOTION_DISCOUNT, Discounts::PercentageDiscount.new(cmd.amount))
order.apply_discount(Discounts::PercentageDiscount.new(Discounts::TIME_PROMOTION_DISCOUNT, cmd.amount))
end
end
end

class ResetTimePromotionDiscountHandler
class RemoveTimePromotionDiscountHandler
def initialize(event_store)
@repository = Infra::AggregateRootRepository.new(event_store)
end

def call(cmd)
@repository.with_aggregate(Offer, cmd.aggregate_id) do |order|
order.reset_discount(Discounts::TIME_PROMOTION_DISCOUNT)
order.remove_discount(Discounts::TIME_PROMOTION_DISCOUNT)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion ecommerce/pricing/test/apply_time_promotion_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def percentage_discount_set_event(order_id, amount)
end

def percentage_discount_reset_event(order_id)
PercentageDiscountReset.new(
PercentageDiscountRemoved.new(
data: {
order_id: order_id,
type: Pricing::Discounts::TIME_PROMOTION_DISCOUNT
Expand Down
28 changes: 14 additions & 14 deletions ecommerce/pricing/test/pricing_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,19 @@ def test_resets_time_promotion_discount

assert_events_contain(
stream,
PercentageDiscountReset.new(
PercentageDiscountRemoved.new(
data: {
order_id: order_id,
type: Discounts::TIME_PROMOTION_DISCOUNT
}
)
) { reset_time_promotion_discount(order_id) }
) { remove_time_promotion_discount(order_id) }
end

def test_does_not_reset_time_promotion_discount_if_there_is_none
def test_does_not_remove_time_promotion_discount_if_there_is_none
order_id = SecureRandom.uuid

assert_raises(NotPossibleToResetWithoutDiscount) { reset_time_promotion_discount(order_id) }
assert_raises(NotPossibleToRemoveWithoutDiscount) { remove_time_promotion_discount(order_id) }
end

def test_calculates_total_value_with_discount
Expand Down Expand Up @@ -200,7 +200,7 @@ def test_calculates_total_value_with_discount
end
assert_events_contain(
stream,
PercentageDiscountReset.new(
PercentageDiscountRemoved.new(
data: {
order_id: order_id,
type: Pricing::Discounts::GENERAL_DISCOUNT
Expand All @@ -215,7 +215,7 @@ def test_calculates_total_value_with_discount
)
) do
run_command(
Pricing::ResetPercentageDiscount.new(order_id: order_id, type: Pricing::Discounts::GENERAL_DISCOUNT)
Pricing::RemovePercentageDiscount.new(order_id: order_id, type: Pricing::Discounts::GENERAL_DISCOUNT)
)
end
end
Expand Down Expand Up @@ -305,7 +305,7 @@ def test_changing_discount_not_possible_when_discount_is_reset
Pricing::SetPercentageDiscount.new(order_id: order_id, amount: 10)
)
run_command(
Pricing::ResetPercentageDiscount.new(order_id: order_id)
Pricing::RemovePercentageDiscount.new(order_id: order_id)
)

assert_raises NotPossibleToChangeDiscount do
Expand Down Expand Up @@ -399,7 +399,7 @@ def test_resetting_discount_possible_when_discount_has_been_set_and_then_changed

assert_events_contain(
stream,
PercentageDiscountReset.new(
PercentageDiscountRemoved.new(
data: {
order_id: order_id,
type: Discounts::GENERAL_DISCOUNT
Expand All @@ -414,7 +414,7 @@ def test_resetting_discount_possible_when_discount_has_been_set_and_then_changed
)
) do
run_command(
Pricing::ResetPercentageDiscount.new(order_id: order_id, type: Discounts::GENERAL_DISCOUNT)
Pricing::RemovePercentageDiscount.new(order_id: order_id, type: Discounts::GENERAL_DISCOUNT)
)
end
end
Expand All @@ -424,20 +424,20 @@ def test_resetting_with_missing_discount_not_possible
set_price(product_1_id, 20)
order_id = SecureRandom.uuid
add_item(order_id, product_1_id)
assert_raises NotPossibleToResetWithoutDiscount do
assert_raises NotPossibleToRemoveWithoutDiscount do
run_command(
Pricing::ResetPercentageDiscount.new(order_id: order_id)
Pricing::RemovePercentageDiscount.new(order_id: order_id)
)
end
run_command(
Pricing::SetPercentageDiscount.new(order_id: order_id, amount: 10)
)
run_command(
Pricing::ResetPercentageDiscount.new(order_id: order_id)
Pricing::RemovePercentageDiscount.new(order_id: order_id)
)
assert_raises NotPossibleToResetWithoutDiscount do
assert_raises NotPossibleToRemoveWithoutDiscount do
run_command(
Pricing::ResetPercentageDiscount.new(order_id: order_id)
Pricing::RemovePercentageDiscount.new(order_id: order_id)
)
end
end
Expand Down
4 changes: 2 additions & 2 deletions ecommerce/pricing/test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ def set_time_promotion_discount(order_id, amount)
run_command(SetTimePromotionDiscount.new(order_id: order_id, amount: amount))
end

def reset_time_promotion_discount(order_id)
run_command(ResetTimePromotionDiscount.new(order_id: order_id))
def remove_time_promotion_discount(order_id)
run_command(RemoveTimePromotionDiscount.new(order_id: order_id))
end

def fake_name
Expand Down
4 changes: 2 additions & 2 deletions rails_application/app/controllers/orders_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ def update_discount
redirect_to edit_order_path(@order_id)
end

def reset_discount
def remove_discount
@order_id = params[:id]
command_bus.(Pricing::ResetPercentageDiscount.new(order_id: @order_id))
command_bus.(Pricing::RemovePercentageDiscount.new(order_id: @order_id))

redirect_to edit_order_path(@order_id)
end
Expand Down
Loading

0 comments on commit e668817

Please sign in to comment.