From 51340bf72229f3e920d56d6dd70072e013a81f10 Mon Sep 17 00:00:00 2001 From: marlena-b Date: Sun, 17 Nov 2024 17:17:57 +0100 Subject: [PATCH] Refactor --- ecommerce/pricing/lib/pricing.rb | 8 +- .../lib/pricing/apply_time_promotion.rb | 2 + ecommerce/pricing/lib/pricing/discounts.rb | 16 +--- ecommerce/pricing/lib/pricing/events.rb | 12 +-- ecommerce/pricing/lib/pricing/offer.rb | 65 ++++--------- ecommerce/pricing/lib/pricing/services.rb | 10 +- .../pricing/test/apply_time_promotion_test.rb | 23 +++-- ecommerce/pricing/test/discounts_test.rb | 32 ------- ecommerce/pricing/test/pricing_test.rb | 48 +++++++--- ecommerce/pricing/test/time_promotion_test.rb | 5 +- .../app/read_models/orders/configuration.rb | 4 +- .../app/read_models/orders/reset_discount.rb | 2 + .../reset_time_promotion_discount_value.rb | 12 +++ .../app/read_models/orders/update_discount.rb | 2 + .../update_time_promotion_discount_value.rb | 2 + .../test/integration/orders_test.rb | 2 +- .../test/orders/broadcast_test.rb | 2 + .../test/orders/discount_test.rb | 52 ++++++++++- ...eset_time_promotion_discount_value_test.rb | 91 +++++++++++++++++++ ...date_time_promotion_discount_value_test.rb | 1 + 20 files changed, 251 insertions(+), 140 deletions(-) create mode 100644 rails_application/app/read_models/orders/reset_time_promotion_discount_value.rb create mode 100644 rails_application/test/orders/reset_time_promotion_discount_value_test.rb diff --git a/ecommerce/pricing/lib/pricing.rb b/ecommerce/pricing/lib/pricing.rb index c58722a6c..adb282187 100644 --- a/ecommerce/pricing/lib/pricing.rb +++ b/ecommerce/pricing/lib/pricing.rb @@ -115,9 +115,7 @@ def call(event_store, command_bus) PercentageDiscountReset, PercentageDiscountChanged, ProductMadeFreeForOrder, - FreeProductRemovedFromOrder, - TimePromotionDiscountSet, - TimePromotionDiscountReset + FreeProductRemovedFromOrder ]) event_store.subscribe(CalculateOrderTotalSubAmountsValue, to: [ PriceItemAdded, @@ -126,9 +124,7 @@ def call(event_store, command_bus) PercentageDiscountReset, PercentageDiscountChanged, ProductMadeFreeForOrder, - FreeProductRemovedFromOrder, - TimePromotionDiscountSet, - TimePromotionDiscountReset + FreeProductRemovedFromOrder ]) end end diff --git a/ecommerce/pricing/lib/pricing/apply_time_promotion.rb b/ecommerce/pricing/lib/pricing/apply_time_promotion.rb index 2630faf3a..3281919cd 100644 --- a/ecommerce/pricing/lib/pricing/apply_time_promotion.rb +++ b/ecommerce/pricing/lib/pricing/apply_time_promotion.rb @@ -8,6 +8,8 @@ def call(event) else command_bus.(ResetTimePromotionDiscount.new(order_id: event.data.fetch(:order_id))) end + + rescue NotPossibleToAssignDiscountTwice, NotPossibleToResetWithoutDiscount end private diff --git a/ecommerce/pricing/lib/pricing/discounts.rb b/ecommerce/pricing/lib/pricing/discounts.rb index ec5084e2f..97e99cfb5 100644 --- a/ecommerce/pricing/lib/pricing/discounts.rb +++ b/ecommerce/pricing/lib/pricing/discounts.rb @@ -1,5 +1,8 @@ module Pricing module Discounts + GENERAL_DISCOUNT = "general_discount" + TIME_PROMOTION_DISCOUNT = "time_promotion_discount" + class UnacceptableDiscountRange < StandardError end @@ -33,10 +36,6 @@ def add(other_discount) PercentageDiscount.new(new_value) end - def ==(other) - value == other.value - end - def exists? true end @@ -57,16 +56,7 @@ def add(other_discount) other_discount end - def value - 0 - end - - def ==(other) - value == other.value - end - def exists? - false end end end diff --git a/ecommerce/pricing/lib/pricing/events.rb b/ecommerce/pricing/lib/pricing/events.rb index 246a6b433..a985f7652 100644 --- a/ecommerce/pricing/lib/pricing/events.rb +++ b/ecommerce/pricing/lib/pricing/events.rb @@ -34,18 +34,10 @@ class PriceItemValueCalculated < Infra::Event class PercentageDiscountSet < Infra::Event attribute :order_id, Infra::Types::UUID + attribute :type, Infra::Types::String attribute :amount, Infra::Types::PercentageDiscount end - class TimePromotionDiscountSet < Infra::Event - attribute :order_id, Infra::Types::UUID - attribute :amount, Infra::Types::PercentageDiscount - end - - class TimePromotionDiscountReset < Infra::Event - attribute :order_id, Infra::Types::UUID - end - class PriceItemAdded < Infra::Event attribute :order_id, Infra::Types::UUID attribute :product_id, Infra::Types::UUID @@ -58,10 +50,12 @@ class PriceItemRemoved < Infra::Event class PercentageDiscountReset < Infra::Event attribute :order_id, Infra::Types::UUID + attribute :type, Infra::Types::String end class PercentageDiscountChanged < Infra::Event attribute :order_id, Infra::Types::UUID + attribute :type, Infra::Types::String attribute :amount, Infra::Types::Price end diff --git a/ecommerce/pricing/lib/pricing/offer.rb b/ecommerce/pricing/lib/pricing/offer.rb index dc672ca27..dca2f3dab 100644 --- a/ecommerce/pricing/lib/pricing/offer.rb +++ b/ecommerce/pricing/lib/pricing/offer.rb @@ -5,8 +5,7 @@ class Offer def initialize(id) @id = id @list = List.new - @discount = Discounts::NoPercentageDiscount.new - @time_promotion_discount = Discounts::NoPercentageDiscount.new + @discounts = {} end def add_item(product_id) @@ -27,50 +26,34 @@ def remove_item(product_id) ) end - def apply_discount(discount) - raise NotPossibleToAssignDiscountTwice if @discount.exists? + def apply_discount(type, discount) + raise NotPossibleToAssignDiscountTwice if @discounts.include?(type) apply PercentageDiscountSet.new( data: { order_id: @id, + type: type, amount: discount.value } ) end - def apply_time_promotion_discount(time_promotion) - return if time_promotion == @time_promotion_discount - apply TimePromotionDiscountSet.new( - data: { - order_id: @id, - amount: time_promotion.value - } - ) - end - - def reset_time_promotion_discount - return unless @time_promotion_discount.exists? - apply TimePromotionDiscountReset.new( - data: { - order_id: @id - } - ) - end - - def change_discount(discount) - raise NotPossibleToChangeDiscount unless @discount.exists? + def change_discount(type, discount) + raise NotPossibleToChangeDiscount unless @discounts.include?(type) apply PercentageDiscountChanged.new( data: { order_id: @id, + type: type, amount: discount.value } ) end - def reset_discount - raise NotPossibleToResetWithoutDiscount unless @discount.exists? + def reset_discount(type) + raise NotPossibleToResetWithoutDiscount unless @discounts.include?(type) apply PercentageDiscountReset.new( data: { - order_id: @id + order_id: @id, + type: type } ) end @@ -97,8 +80,8 @@ 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 = @discount.add(@time_promotion_discount).apply(total_value) apply( OrderTotalValueCalculated.new( data: { @@ -112,7 +95,7 @@ def calculate_total_value(pricing_catalog) def calculate_sub_amounts(pricing_catalog) sub_amounts_total = @list.sub_amounts_total(pricing_catalog) - sub_discounts = calculate_total_sub_discounts(pricing_catalog, @time_promotion_discount) + sub_discounts = calculate_total_sub_discounts(pricing_catalog) products = @list.products quantities = @list.quantities @@ -158,23 +141,15 @@ def use_coupon(coupon_id, discount) end on PercentageDiscountSet do |event| - @discount = Discounts::PercentageDiscount.new(event.data.fetch(:amount)) + @discounts[event.data.fetch(:type)] = Discounts::PercentageDiscount.new(event.data.fetch(:amount)) end on PercentageDiscountChanged do |event| - @discount = Discounts::PercentageDiscount.new(event.data.fetch(:amount)) - end - - on TimePromotionDiscountSet do |event| - @time_promotion_discount = Discounts::PercentageDiscount.new(event.data.fetch(:amount)) - end - - on TimePromotionDiscountReset do |event| - @time_promotion_discount = Discounts::NoPercentageDiscount.new + @discounts[event.data.fetch(:type)] = Discounts::PercentageDiscount.new(event.data.fetch(:amount)) end on PercentageDiscountReset do |event| - @discount = Discounts::NoPercentageDiscount.new + @discounts.delete(event.data.fetch(:type)) end on ProductMadeFreeForOrder do |event| @@ -185,8 +160,8 @@ def use_coupon(coupon_id, discount) @list.replace(FreeProduct, Product, event.data.fetch(:product_id)) end - def calculate_total_sub_discounts(pricing_catalog, time_promotions_discount) - @list.sub_discounts(pricing_catalog, time_promotions_discount, @discount) + def calculate_total_sub_discounts(pricing_catalog) + @list.sub_discounts(pricing_catalog, @discounts) end on CouponUsed do |event| @@ -237,10 +212,10 @@ def sub_amounts_total(pricing_catalog) @products_quantities.map { |product, quantity| quantity * pricing_catalog.price_for(product) } end - def sub_discounts(pricing_catalog, time_promotions_discount, discount) + 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 = discount.add(time_promotions_discount).apply(catalog_price_for_single) + with_total_discount_single = discounts.values.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 1e5a1be6f..18f744b29 100644 --- a/ecommerce/pricing/lib/pricing/services.rb +++ b/ecommerce/pricing/lib/pricing/services.rb @@ -21,7 +21,7 @@ def initialize(event_store) def call(cmd) @repository.with_aggregate(Offer, cmd.aggregate_id) do |order| - order.apply_discount(Discounts::PercentageDiscount.new(cmd.amount)) + order.apply_discount(Discounts::GENERAL_DISCOUNT, Discounts::PercentageDiscount.new(cmd.amount)) end end end @@ -33,7 +33,7 @@ def initialize(event_store) def call(cmd) @repository.with_aggregate(Offer, cmd.aggregate_id) do |order| - order.reset_discount + order.reset_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::PercentageDiscount.new(cmd.amount)) + order.change_discount(Discounts::GENERAL_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_time_promotion_discount(Discounts::PercentageDiscount.new(cmd.amount)) + order.apply_discount(Discounts::TIME_PROMOTION_DISCOUNT, Discounts::PercentageDiscount.new(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_time_promotion_discount + order.reset_discount(Discounts::TIME_PROMOTION_DISCOUNT) end end end diff --git a/ecommerce/pricing/test/apply_time_promotion_test.rb b/ecommerce/pricing/test/apply_time_promotion_test.rb index 25f6f1374..b8dbeaea8 100644 --- a/ecommerce/pricing/test/apply_time_promotion_test.rb +++ b/ecommerce/pricing/test/apply_time_promotion_test.rb @@ -12,18 +12,21 @@ def test_applies_biggest_time_promotion_discount create_active_time_promotion(50) create_active_time_promotion(30) - assert_events_contain(stream_name(order_id), time_promotion_discount_set_event(order_id, 50)) do - Pricing::ApplyTimePromotion.new.call(item_added_to_basket_event(order_id, product_id)) + assert_events_contain(stream_name(order_id), percentage_discount_set_event(order_id, 50)) do + Pricing::ApplyTimePromotion.new.call(item_added_to_basket_event(order_id, product_id)) end end def test_resets_time_promotion_discount order_id = SecureRandom.uuid product_id = SecureRandom.uuid + create_active_time_promotion(50) set_time_promotion_discount(order_id, 50) - assert_events_contain(stream_name(order_id), time_promotion_discount_reset_event(order_id)) do + Timecop.travel(1.minute.from_now) do + assert_events_contain(stream_name(order_id), percentage_discount_reset_event(order_id)) do Pricing::ApplyTimePromotion.new.call(item_added_to_basket_event(order_id, product_id)) + end end end @@ -63,22 +66,24 @@ def item_added_to_basket_event(order_id, product_id) end def set_time_promotion_discount(order_id, discount) - run_command(SetTimePromotionDiscount.new(order_id: order_id, amount: 50)) + run_command(SetTimePromotionDiscount.new(order_id: order_id, amount: discount)) end - def time_promotion_discount_set_event(order_id, amount) - TimePromotionDiscountSet.new( + def percentage_discount_set_event(order_id, amount) + PercentageDiscountSet.new( data: { order_id: order_id, + type: Pricing::Discounts::TIME_PROMOTION_DISCOUNT, amount: amount } ) end - def time_promotion_discount_reset_event(order_id) - TimePromotionDiscountReset.new( + def percentage_discount_reset_event(order_id) + PercentageDiscountReset.new( data: { - order_id: order_id + order_id: order_id, + type: Pricing::Discounts::TIME_PROMOTION_DISCOUNT } ) end diff --git a/ecommerce/pricing/test/discounts_test.rb b/ecommerce/pricing/test/discounts_test.rb index cf0fa7c02..b7387cc70 100644 --- a/ecommerce/pricing/test/discounts_test.rb +++ b/ecommerce/pricing/test/discounts_test.rb @@ -55,20 +55,6 @@ def test_cannot_add_to_more_than_100 assert_equal(0, combined.apply(100)) end - - def test_is_equal_to_another_discount - first_discount = PercentageDiscount.new(50) - second_discount = PercentageDiscount.new(50) - - assert_equal(first_discount, second_discount) - end - - def test_is_not_equal_to_another_discount - first_discount = PercentageDiscount.new(50) - second_discount = PercentageDiscount.new(60) - - refute_equal(first_discount, second_discount) - end end class NoPercentageDiscountTest < Test @@ -77,24 +63,6 @@ class NoPercentageDiscountTest < Test def test_doesnt_change_total assert_equal(100, NoPercentageDiscount.new.apply(100)) end - - def test_is_equal_to_another_discount - first_discount = NoPercentageDiscount.new - second_discount = NoPercentageDiscount.new - - assert_equal(first_discount, second_discount) - end - - def test_is_not_equal_to_another_discount - first_discount = NoPercentageDiscount.new - second_discount = PercentageDiscount.new(50) - - refute_equal(first_discount, second_discount) - end - - def test_exists_returns_false - assert_equal false, NoPercentageDiscount.new.exists? - end end end end diff --git a/ecommerce/pricing/test/pricing_test.rb b/ecommerce/pricing/test/pricing_test.rb index f2397a0d6..2067b5a99 100644 --- a/ecommerce/pricing/test/pricing_test.rb +++ b/ecommerce/pricing/test/pricing_test.rb @@ -99,9 +99,10 @@ def test_sets_time_promotion_discount assert_events_contain( stream, - TimePromotionDiscountSet.new( + Pricing::PercentageDiscountSet.new( data: { order_id: order_id, + type: Discounts::TIME_PROMOTION_DISCOUNT, amount: 25 } ) @@ -110,23 +111,24 @@ def test_sets_time_promotion_discount def test_does_not_set_the_same_time_promotion_discount_twice order_id = SecureRandom.uuid - stream = stream_name(order_id) + create_active_time_promotion(25) set_time_promotion_discount(order_id, 25) - assert_events(stream) { set_time_promotion_discount(order_id, 25) } + assert_raises(NotPossibleToAssignDiscountTwice) { set_time_promotion_discount(order_id, 25) } end def test_resets_time_promotion_discount order_id = SecureRandom.uuid stream = stream_name(order_id) + create_active_time_promotion(25) set_time_promotion_discount(order_id, 25) - assert_events_contain( stream, - TimePromotionDiscountReset.new( + PercentageDiscountReset.new( data: { - order_id: order_id + order_id: order_id, + type: Discounts::TIME_PROMOTION_DISCOUNT } ) ) { reset_time_promotion_discount(order_id) } @@ -134,9 +136,8 @@ def test_resets_time_promotion_discount def test_does_not_reset_time_promotion_discount_if_there_is_none order_id = SecureRandom.uuid - stream = stream_name(order_id) - assert_events(stream) { reset_time_promotion_discount(order_id) } + assert_raises(NotPossibleToResetWithoutDiscount) { reset_time_promotion_discount(order_id) } end def test_calculates_total_value_with_discount @@ -160,6 +161,7 @@ def test_calculates_total_value_with_discount PercentageDiscountSet.new( data: { order_id: order_id, + type: Pricing::Discounts::GENERAL_DISCOUNT, amount: 10 } ), @@ -172,7 +174,7 @@ def test_calculates_total_value_with_discount ) ) do run_command( - Pricing::SetPercentageDiscount.new(order_id: order_id, amount: 10) + Pricing::SetPercentageDiscount.new(order_id: order_id, type: Pricing::Discounts::GENERAL_DISCOUNT, amount: 10) ) end assert_events_contain( @@ -180,6 +182,7 @@ def test_calculates_total_value_with_discount PercentageDiscountChanged.new( data: { order_id: order_id, + type: Pricing::Discounts::GENERAL_DISCOUNT, amount: 50 } ), @@ -200,6 +203,7 @@ def test_calculates_total_value_with_discount PercentageDiscountReset.new( data: { order_id: order_id, + type: Pricing::Discounts::GENERAL_DISCOUNT } ), OrderTotalValueCalculated.new( @@ -211,7 +215,7 @@ def test_calculates_total_value_with_discount ) ) do run_command( - Pricing::ResetPercentageDiscount.new(order_id: order_id) + Pricing::ResetPercentageDiscount.new(order_id: order_id, type: Pricing::Discounts::GENERAL_DISCOUNT) ) end end @@ -227,6 +231,7 @@ def test_calculates_total_value_with_100_discount PercentageDiscountSet.new( data: { order_id: order_id, + type: Pricing::Discounts::GENERAL_DISCOUNT, amount: 100 } ), @@ -325,6 +330,7 @@ def test_changing_discount_possible_when_discount_is_set PercentageDiscountChanged.new( data: { order_id: order_id, + type: Pricing::Discounts::GENERAL_DISCOUNT, amount: 100 } ), @@ -360,6 +366,7 @@ def test_changing_discount_possible_more_than_once PercentageDiscountChanged.new( data: { order_id: order_id, + type: Pricing::Discounts::GENERAL_DISCOUNT, amount: 100 } ), @@ -384,17 +391,18 @@ def test_resetting_discount_possible_when_discount_has_been_set_and_then_changed add_item(order_id, product_1_id) stream = stream_name(order_id) run_command( - Pricing::SetPercentageDiscount.new(order_id: order_id, amount: 10) + Pricing::SetPercentageDiscount.new(order_id: order_id, type: Discounts::GENERAL_DISCOUNT,amount: 10) ) run_command( - Pricing::ChangePercentageDiscount.new(order_id: order_id, amount: 20) + Pricing::ChangePercentageDiscount.new(order_id: order_id, type: Discounts::GENERAL_DISCOUNT, amount: 20) ) assert_events_contain( stream, PercentageDiscountReset.new( data: { - order_id: order_id + order_id: order_id, + type: Discounts::GENERAL_DISCOUNT } ), OrderTotalValueCalculated.new( @@ -406,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) + Pricing::ResetPercentageDiscount.new(order_id: order_id, type: Discounts::GENERAL_DISCOUNT) ) end end @@ -443,5 +451,17 @@ def stream_name(order_id) def calculate_sub_amounts(order_id) run_command(CalculateSubAmounts.new(order_id: order_id)) end + + def create_active_time_promotion(discount) + run_command( + Pricing::CreateTimePromotion.new( + time_promotion_id: SecureRandom.uuid, + discount: discount, + start_time: Time.current - 1.minute, + end_time: Time.current + 1.minute, + label: "Last Minute" + ) + ) + end end end diff --git a/ecommerce/pricing/test/time_promotion_test.rb b/ecommerce/pricing/test/time_promotion_test.rb index d23ce0fbd..a3ccd9991 100644 --- a/ecommerce/pricing/test/time_promotion_test.rb +++ b/ecommerce/pricing/test/time_promotion_test.rb @@ -46,6 +46,10 @@ def test_calculates_total_value_with_time_promotion set_price(product_1_id, 20) add_item(order_id, product_1_id) stream = stream_name(order_id) + time_promotion_id = SecureRandom.uuid + start_time = Time.current - 1 + end_time = Time.current + 1 + set_time_promotion_range(time_promotion_id, start_time, end_time, 50) run_command(SetTimePromotionDiscount.new(order_id: order_id, amount: 50)) @@ -81,7 +85,6 @@ def test_calculates_sub_amounts_with_combined_discounts add_item(order_id, product_1_id) add_item(order_id, product_2_id) add_item(order_id, product_2_id) - run_command(SetTimePromotionDiscount.new(order_id: order_id, amount: 50)) run_command( Pricing::SetPercentageDiscount.new(order_id: order_id, amount: 10) diff --git a/rails_application/app/read_models/orders/configuration.rb b/rails_application/app/read_models/orders/configuration.rb index 87553986c..fb09677af 100644 --- a/rails_application/app/read_models/orders/configuration.rb +++ b/rails_application/app/read_models/orders/configuration.rb @@ -46,8 +46,8 @@ def call(event_store) event_store.subscribe(ExpireOrder.new, to: [Ordering::OrderExpired]) event_store.subscribe(ConfirmOrder.new, to: [Fulfillment::OrderConfirmed]) event_store.subscribe(CancelOrder.new, to: [Fulfillment::OrderCancelled]) - event_store.subscribe(UpdateTimePromotionDiscountValue.new, to: [Pricing::TimePromotionDiscountSet]) - + event_store.subscribe(UpdateTimePromotionDiscountValue.new, to: [Pricing::PercentageDiscountSet]) + event_store.subscribe(ResetTimePromotionDiscountValue.new, to: [Pricing::PercentageDiscountReset]) subscribe( ->(event) { broadcast_order_state_change(event.data.fetch(:order_id), 'Submitted') }, diff --git a/rails_application/app/read_models/orders/reset_discount.rb b/rails_application/app/read_models/orders/reset_discount.rb index 8c6375765..420373486 100644 --- a/rails_application/app/read_models/orders/reset_discount.rb +++ b/rails_application/app/read_models/orders/reset_discount.rb @@ -1,6 +1,8 @@ module Orders class ResetDiscount def call(event) + return unless event.data.fetch(:type) == Pricing::Discounts::GENERAL_DISCOUNT + order = Order.find_by_uid(event.data.fetch(:order_id)) order.percentage_discount = nil order.save! diff --git a/rails_application/app/read_models/orders/reset_time_promotion_discount_value.rb b/rails_application/app/read_models/orders/reset_time_promotion_discount_value.rb new file mode 100644 index 000000000..c4741ab5c --- /dev/null +++ b/rails_application/app/read_models/orders/reset_time_promotion_discount_value.rb @@ -0,0 +1,12 @@ +module Orders + class ResetTimePromotionDiscountValue + def call(event) + return unless event.data.fetch(:type) == Pricing::Discounts::TIME_PROMOTION_DISCOUNT + + order = Order.find_by(uid: event.data.fetch(:order_id)) + + order.time_promotion_discount_value = nil + order.save! + end + end +end diff --git a/rails_application/app/read_models/orders/update_discount.rb b/rails_application/app/read_models/orders/update_discount.rb index cf55f2e27..710308192 100644 --- a/rails_application/app/read_models/orders/update_discount.rb +++ b/rails_application/app/read_models/orders/update_discount.rb @@ -1,6 +1,8 @@ module Orders class UpdateDiscount def call(event) + return unless event.data.fetch(:type) == Pricing::Discounts::GENERAL_DISCOUNT + order = Order.find_or_create_by(uid: event.data.fetch(:order_id)) if is_newest_value?(event, order) order.percentage_discount = event.data.fetch(:amount) diff --git a/rails_application/app/read_models/orders/update_time_promotion_discount_value.rb b/rails_application/app/read_models/orders/update_time_promotion_discount_value.rb index 5fb4a62ca..aebf0ea25 100644 --- a/rails_application/app/read_models/orders/update_time_promotion_discount_value.rb +++ b/rails_application/app/read_models/orders/update_time_promotion_discount_value.rb @@ -1,6 +1,8 @@ module Orders class UpdateTimePromotionDiscountValue def call(event) + return unless event.data.fetch(:type) == Pricing::Discounts::TIME_PROMOTION_DISCOUNT + order = Order.find_or_create_by(uid: event.data.fetch(:order_id)) order.time_promotion_discount_value = event.data.fetch(:amount) diff --git a/rails_application/test/integration/orders_test.rb b/rails_application/test/integration/orders_test.rb index 4eca06aed..d5e211c43 100644 --- a/rails_application/test/integration/orders_test.rb +++ b/rails_application/test/integration/orders_test.rb @@ -383,7 +383,7 @@ def create_active_time_promotion(discount) label: "Last Minute", discount: discount, start_time: Time.current - 1, - end_time: Time.current + 1 + end_time: Time.current + 1.minute } end end diff --git a/rails_application/test/orders/broadcast_test.rb b/rails_application/test/orders/broadcast_test.rb index a4a21df49..9d8bb5653 100644 --- a/rails_application/test/orders/broadcast_test.rb +++ b/rails_application/test/orders/broadcast_test.rb @@ -210,6 +210,7 @@ def test_broadcast_update_discount Pricing::PercentageDiscountSet.new( data: { order_id: order_1_id, + type: Pricing::Discounts::GENERAL_DISCOUNT, amount: 30 } ) @@ -221,6 +222,7 @@ def test_broadcast_update_discount Pricing::PercentageDiscountSet.new( data: { order_id: order_id, + type: Pricing::Discounts::GENERAL_DISCOUNT, amount: 30 } ) diff --git a/rails_application/test/orders/discount_test.rb b/rails_application/test/orders/discount_test.rb index bd9d9de72..37184b605 100644 --- a/rails_application/test/orders/discount_test.rb +++ b/rails_application/test/orders/discount_test.rb @@ -18,6 +18,7 @@ def test_discount_set assert_equal 50, order.total_value assert_equal 45, order.discounted_value assert_equal 10, order.percentage_discount + assert_nil order.time_promotion_discount_value assert event_store.event_in_stream?(event_store.read.of_type([Pricing::PercentageDiscountSet]).last.event_id, "Orders$all") end @@ -36,6 +37,7 @@ def test_discount_changed assert_equal 50, order.total_value assert_equal 49.5, order.discounted_value assert_equal 1, order.percentage_discount + assert_nil order.time_promotion_discount_value assert event_store.event_in_stream?(event_store.read.of_type([Pricing::PercentageDiscountChanged]).last.event_id, "Orders$all") end @@ -57,6 +59,21 @@ def test_reset_discount assert event_store.event_in_stream?(event_store.read.of_type([Pricing::PercentageDiscountReset]).last.event_id, "Orders$all") end + def test_does_not_reset_percentage_discount_when_time_promotion_reset + customer_id = SecureRandom.uuid + product_id = SecureRandom.uuid + order_id = SecureRandom.uuid + create_active_time_promotion + customer_registered(customer_id) + prepare_product(product_id) + item_added_to_basket(order_id, product_id) + set_percentage_discount(order_id) + + assert_no_changes -> { Orders::Order.find_by(uid: order_id).percentage_discount } do + travel_to(1.minute.from_now) { item_added_to_basket(order_id, product_id) } + end + end + def test_newest_event_is_always_applied customer_id = SecureRandom.uuid product_id = SecureRandom.uuid @@ -65,8 +82,26 @@ def test_newest_event_is_always_applied prepare_product(product_id) item_added_to_basket(order_id, product_id) - event_store.publish(Pricing::PercentageDiscountSet.new(data: { order_id: order_id, amount: 30 }, metadata: { timestamp: Time.current })) - event_store.publish(Pricing::PercentageDiscountSet.new(data: { order_id: order_id, amount: 20 }, metadata: { timestamp: 1.minute.ago })) + event_store.publish(Pricing::PercentageDiscountSet.new( + data: { + order_id: order_id, + type: Pricing::Discounts::GENERAL_DISCOUNT, + amount: 30 + }, + metadata: { + timestamp: Time.current + }) + ) + event_store.publish(Pricing::PercentageDiscountSet.new( + data: { + order_id: order_id, + type: Pricing::Discounts::GENERAL_DISCOUNT, + amount: 20 + }, + metadata: { + timestamp: 1.minute.ago + }) + ) assert_equal 30, Orders::Order.find_by(uid: order_id).percentage_discount end @@ -111,6 +146,17 @@ def customer_registered(customer_id) def event_store Rails.configuration.event_store end + + def create_active_time_promotion + run_command( + Pricing::CreateTimePromotion.new( + time_promotion_id: SecureRandom.uuid, + discount: 50, + start_time: Time.current - 1, + end_time: Time.current + 1, + label: "Last Minute" + ) + ) + end end end - 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 new file mode 100644 index 000000000..a835282a3 --- /dev/null +++ b/rails_application/test/orders/reset_time_promotion_discount_value_test.rb @@ -0,0 +1,91 @@ +require "test_helper" + +module Orders + class ResetTimePromotionDiscountValueTest < InMemoryTestCase + cover "Orders*" + + def test_resets_time_promotion_discount_value + customer_id = SecureRandom.uuid + product_id = SecureRandom.uuid + order_id = SecureRandom.uuid + create_active_time_promotion + customer_registered(customer_id) + prepare_product(product_id) + item_added_to_basket(order_id, product_id) + + travel_to(1.minute.from_now) do + item_added_to_basket(order_id, product_id) + order = Orders::Order.find_by(uid: order_id) + assert_nil order.time_promotion_discount_value + end + end + + def test_does_not_reset_time_promotion_when_general_discount_reset + customer_id = SecureRandom.uuid + product_id = SecureRandom.uuid + order_id = SecureRandom.uuid + create_active_time_promotion + customer_registered(customer_id) + prepare_product(product_id) + item_added_to_basket(order_id, product_id) + set_percentage_discount(order_id) + + assert_no_changes -> { Orders::Order.find_by(uid: order_id).time_promotion_discount_value } do + reset_percentage_discount(order_id) + end + end + + private + + def item_added_to_basket(order_id, product_id) + event_store.publish(Pricing::PriceItemAdded.new(data: { product_id: product_id, order_id: order_id })) + end + + def prepare_product(product_id) + run_command( + ProductCatalog::RegisterProduct.new( + product_id: product_id, + ) + ) + run_command( + ProductCatalog::NameProduct.new( + product_id: product_id, + name: "test" + ) + ) + run_command(Pricing::SetPrice.new(product_id: product_id, price: 50)) + end + + def customer_registered(customer_id) + event_store.publish(Crm::CustomerRegistered.new(data: { customer_id: customer_id, name: "Arkency" })) + end + + def create_active_time_promotion + run_command( + Pricing::CreateTimePromotion.new( + time_promotion_id: SecureRandom.uuid, + discount: 50, + start_time: Time.current - 1, + end_time: Time.current + 1, + label: "Last Minute" + ) + ) + end + + def event_store + Rails.configuration.event_store + end + + def set_percentage_discount(order_id) + run_command( + Pricing::SetPercentageDiscount.new(order_id: order_id, amount: 10) + ) + end + + def reset_percentage_discount(order_id) + run_command( + Pricing::ResetPercentageDiscount.new(order_id: order_id, type: Pricing::Discounts::GENERAL_DISCOUNT) + ) + end + end +end diff --git a/rails_application/test/orders/update_time_promotion_discount_value_test.rb b/rails_application/test/orders/update_time_promotion_discount_value_test.rb index cb650b8d2..b73b92f0b 100644 --- a/rails_application/test/orders/update_time_promotion_discount_value_test.rb +++ b/rails_application/test/orders/update_time_promotion_discount_value_test.rb @@ -15,6 +15,7 @@ def test_updates_time_promotion_discount_value order = Orders::Order.find_by(uid: order_id) assert_equal 50, order.time_promotion_discount_value + assert_nil order.percentage_discount end private