From 80c4e192b50dd8285000692ed2bbeb1ecf1ceaf9 Mon Sep 17 00:00:00 2001 From: marlena-b Date: Mon, 25 Nov 2024 17:24:25 +0100 Subject: [PATCH] Refactor discounts --- ecommerce/pricing/lib/pricing.rb | 4 +-- .../lib/pricing/apply_time_promotion.rb | 2 +- ecommerce/pricing/lib/pricing/commands.rb | 2 +- ecommerce/pricing/lib/pricing/discounts.rb | 5 +-- ecommerce/pricing/lib/pricing/offer.rb | 33 +++++++++++-------- ecommerce/pricing/lib/pricing/services.rb | 14 ++++---- ecommerce/pricing/test/pricing_test.rb | 18 +++++----- .../app/controllers/orders_controller.rb | 2 +- .../test/client_orders/discount_test.rb | 3 +- .../test/orders/discount_test.rb | 2 +- ...eset_time_promotion_discount_value_test.rb | 2 +- 11 files changed, 46 insertions(+), 41 deletions(-) diff --git a/ecommerce/pricing/lib/pricing.rb b/ecommerce/pricing/lib/pricing.rb index adb28218..8cd69808 100644 --- a/ecommerce/pricing/lib/pricing.rb +++ b/ecommerce/pricing/lib/pricing.rb @@ -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, diff --git a/ecommerce/pricing/lib/pricing/apply_time_promotion.rb b/ecommerce/pricing/lib/pricing/apply_time_promotion.rb index 3281919c..7e820d9c 100644 --- a/ecommerce/pricing/lib/pricing/apply_time_promotion.rb +++ b/ecommerce/pricing/lib/pricing/apply_time_promotion.rb @@ -9,7 +9,7 @@ def call(event) command_bus.(ResetTimePromotionDiscount.new(order_id: event.data.fetch(:order_id))) end - rescue NotPossibleToAssignDiscountTwice, NotPossibleToResetWithoutDiscount + rescue NotPossibleToAssignDiscountTwice, NotPossibleToRemoveWithoutDiscount end private diff --git a/ecommerce/pricing/lib/pricing/commands.rb b/ecommerce/pricing/lib/pricing/commands.rb index 832f9473..4a09251c 100644 --- a/ecommerce/pricing/lib/pricing/commands.rb +++ b/ecommerce/pricing/lib/pricing/commands.rb @@ -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 diff --git a/ecommerce/pricing/lib/pricing/discounts.rb b/ecommerce/pricing/lib/pricing/discounts.rb index 97e99cfb..e72c4976 100644 --- a/ecommerce/pricing/lib/pricing/discounts.rb +++ b/ecommerce/pricing/lib/pricing/discounts.rb @@ -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 diff --git a/ecommerce/pricing/lib/pricing/offer.rb b/ecommerce/pricing/lib/pricing/offer.rb index dca2f3da..0aee37db 100644 --- a/ecommerce/pricing/lib/pricing/offer.rb +++ b/ecommerce/pricing/lib/pricing/offer.rb @@ -5,7 +5,7 @@ class Offer def initialize(id) @id = id @list = List.new - @discounts = {} + @discounts = [] end def add_item(product_id) @@ -26,30 +26,30 @@ 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) + def remove_discount(type) + raise NotPossibleToRemoveWithoutDiscount unless discount_exists?(type) apply PercentageDiscountReset.new( data: { order_id: @id, @@ -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( @@ -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)) + @discounts.delete_if { |discount| discount.type == event.data.fetch(:type) } end on ProductMadeFreeForOrder do |event| @@ -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 @@ -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 diff --git a/ecommerce/pricing/lib/pricing/services.rb b/ecommerce/pricing/lib/pricing/services.rb index 18f744b2..11d82997 100644 --- a/ecommerce/pricing/lib/pricing/services.rb +++ b/ecommerce/pricing/lib/pricing/services.rb @@ -2,7 +2,7 @@ module Pricing class NotPossibleToAssignDiscountTwice < StandardError end - class NotPossibleToResetWithoutDiscount < StandardError + class NotPossibleToRemoveWithoutDiscount < StandardError end class NotPossibleToChangeDiscount < StandardError @@ -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 @@ -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 @@ -57,7 +57,7 @@ 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 @@ -69,7 +69,7 @@ def initialize(event_store) 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 diff --git a/ecommerce/pricing/test/pricing_test.rb b/ecommerce/pricing/test/pricing_test.rb index 2067b5a9..6d8a1828 100644 --- a/ecommerce/pricing/test/pricing_test.rb +++ b/ecommerce/pricing/test/pricing_test.rb @@ -137,7 +137,7 @@ def test_resets_time_promotion_discount def test_does_not_reset_time_promotion_discount_if_there_is_none order_id = SecureRandom.uuid - assert_raises(NotPossibleToResetWithoutDiscount) { reset_time_promotion_discount(order_id) } + assert_raises(NotPossibleToRemoveWithoutDiscount) { reset_time_promotion_discount(order_id) } end def test_calculates_total_value_with_discount @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/rails_application/app/controllers/orders_controller.rb b/rails_application/app/controllers/orders_controller.rb index 76bc55bc..c5b96e6b 100644 --- a/rails_application/app/controllers/orders_controller.rb +++ b/rails_application/app/controllers/orders_controller.rb @@ -51,7 +51,7 @@ def update_discount def reset_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 diff --git a/rails_application/test/client_orders/discount_test.rb b/rails_application/test/client_orders/discount_test.rb index 29e3990c..559601a9 100644 --- a/rails_application/test/client_orders/discount_test.rb +++ b/rails_application/test/client_orders/discount_test.rb @@ -57,7 +57,7 @@ def test_reset_discount private def reset_percentage_discount(order_id) - run_command(Pricing::ResetPercentageDiscount.new(order_id: order_id)) + run_command(Pricing::RemovePercentageDiscount.new(order_id: order_id)) end def set_percentage_discount(order_id) @@ -96,4 +96,3 @@ def event_store end end end - diff --git a/rails_application/test/orders/discount_test.rb b/rails_application/test/orders/discount_test.rb index 37184b60..43eb534a 100644 --- a/rails_application/test/orders/discount_test.rb +++ b/rails_application/test/orders/discount_test.rb @@ -109,7 +109,7 @@ def test_newest_event_is_always_applied private def reset_percentage_discount(order_id) - run_command(Pricing::ResetPercentageDiscount.new(order_id: order_id)) + run_command(Pricing::RemovePercentageDiscount.new(order_id: order_id)) end def set_percentage_discount(order_id) diff --git a/rails_application/test/orders/reset_time_promotion_discount_value_test.rb b/rails_application/test/orders/reset_time_promotion_discount_value_test.rb index a835282a..51e969a5 100644 --- a/rails_application/test/orders/reset_time_promotion_discount_value_test.rb +++ b/rails_application/test/orders/reset_time_promotion_discount_value_test.rb @@ -84,7 +84,7 @@ def set_percentage_discount(order_id) def reset_percentage_discount(order_id) 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