From 6904d923e9195c54ab63fd308151b0b614f0a146 Mon Sep 17 00:00:00 2001 From: marlena-b Date: Mon, 2 Dec 2024 12:40:50 +0100 Subject: [PATCH] display time promotion on client order --- .../pricing/test/apply_time_promotion_test.rb | 6 +- ecommerce/pricing/test/pricing_test.rb | 8 +- .../client_orders/configuration.rb | 2 + .../client_orders/order_handlers.rb | 24 +++++ .../client_orders/rendering/show_order.rb | 8 ++ ...ime_promotion_discount_to_client_orders.rb | 5 ++ rails_application/db/schema.rb | 3 +- .../test/client_orders/discount_test.rb | 20 ++++- .../time_promotion_discount_test.rb | 88 +++++++++++++++++++ .../test/integration/client_orders_test.rb | 1 + .../test/orders/discount_test.rb | 2 +- .../remove_time_promotion_discount_test.rb | 4 +- 12 files changed, 158 insertions(+), 13 deletions(-) create mode 100644 rails_application/db/migrate/20241129122521_add_time_promotion_discount_to_client_orders.rb create mode 100644 rails_application/test/client_orders/time_promotion_discount_test.rb diff --git a/ecommerce/pricing/test/apply_time_promotion_test.rb b/ecommerce/pricing/test/apply_time_promotion_test.rb index adaddd06..00f39425 100644 --- a/ecommerce/pricing/test/apply_time_promotion_test.rb +++ b/ecommerce/pricing/test/apply_time_promotion_test.rb @@ -17,14 +17,14 @@ def test_applies_biggest_time_promotion_discount end end - def test_resets_time_promotion_discount + def test_remove_time_promotion_discount order_id = SecureRandom.uuid product_id = SecureRandom.uuid create_active_time_promotion(50) set_time_promotion_discount(order_id, 50) Timecop.travel(1.minute.from_now) do - assert_events_contain(stream_name(order_id), percentage_discount_reset_event(order_id)) do + assert_events_contain(stream_name(order_id), percentage_discount_removed_event(order_id)) do Pricing::ApplyTimePromotion.new.call(item_added_to_basket_event(order_id, product_id)) end end @@ -79,7 +79,7 @@ def percentage_discount_set_event(order_id, amount) ) end - def percentage_discount_reset_event(order_id) + def percentage_discount_removed_event(order_id) PercentageDiscountRemoved.new( data: { order_id: order_id, diff --git a/ecommerce/pricing/test/pricing_test.rb b/ecommerce/pricing/test/pricing_test.rb index 174d6c28..fc9cd034 100644 --- a/ecommerce/pricing/test/pricing_test.rb +++ b/ecommerce/pricing/test/pricing_test.rb @@ -117,7 +117,7 @@ def test_does_not_set_the_same_time_promotion_discount_twice assert_raises(NotPossibleToAssignDiscountTwice) { set_time_promotion_discount(order_id, 25) } end - def test_resets_time_promotion_discount + def test_removes_time_promotion_discount order_id = SecureRandom.uuid stream = stream_name(order_id) create_active_time_promotion(25) @@ -296,7 +296,7 @@ def test_changing_discount_not_possible_when_discount_is_not_set end end - def test_changing_discount_not_possible_when_discount_is_reset + def test_changing_discount_not_possible_when_discount_is_removed product_1_id = SecureRandom.uuid set_price(product_1_id, 20) order_id = SecureRandom.uuid @@ -384,7 +384,7 @@ def test_changing_discount_possible_more_than_once end end - def test_resetting_discount_possible_when_discount_has_been_set_and_then_changed + def test_removing_discount_possible_when_discount_has_been_set_and_then_changed product_1_id = SecureRandom.uuid set_price(product_1_id, 20) order_id = SecureRandom.uuid @@ -419,7 +419,7 @@ def test_resetting_discount_possible_when_discount_has_been_set_and_then_changed end end - def test_resetting_with_missing_discount_not_possible + def test_removing_with_missing_discount_not_possible product_1_id = SecureRandom.uuid set_price(product_1_id, 20) order_id = SecureRandom.uuid diff --git a/rails_application/app/read_models/client_orders/configuration.rb b/rails_application/app/read_models/client_orders/configuration.rb index 47df64fb..e48ee5ad 100644 --- a/rails_application/app/read_models/client_orders/configuration.rb +++ b/rails_application/app/read_models/client_orders/configuration.rb @@ -55,6 +55,8 @@ def call(event_store) event_store.subscribe(ProductHandlers::ChangeProductPrice, to: [Pricing::PriceSet]) event_store.subscribe(ProductHandlers::RegisterProduct, to: [ProductCatalog::ProductRegistered]) event_store.subscribe(ProductHandlers::UpdateProductAvailability, to: [Inventory::AvailabilityChanged]) + event_store.subscribe(OrderHandlers::UpdateTimePromotionDiscount, to: [Pricing::PercentageDiscountSet]) + event_store.subscribe(OrderHandlers::RemoveTimePromotionDiscount, to: [Pricing::PercentageDiscountRemoved]) event_store.subscribe(OrderHandlers::UpdateDiscount, to: [Pricing::PercentageDiscountSet, Pricing::PercentageDiscountChanged]) event_store.subscribe(OrderHandlers::RemoveDiscount, to: [Pricing::PercentageDiscountRemoved]) event_store.subscribe(OrderHandlers::UpdateOrderTotalValue, to: [Pricing::OrderTotalValueCalculated]) diff --git a/rails_application/app/read_models/client_orders/order_handlers.rb b/rails_application/app/read_models/client_orders/order_handlers.rb index 33d6a1ce..3edc2c3d 100644 --- a/rails_application/app/read_models/client_orders/order_handlers.rb +++ b/rails_application/app/read_models/client_orders/order_handlers.rb @@ -19,12 +19,24 @@ def call(event) class UpdateDiscount def call(event) + return unless event.data.fetch(:type) == Pricing::Discounts::GENERAL_DISCOUNT + order = Order.find_or_create_by!(order_uid: event.data.fetch(:order_id)) order.percentage_discount = event.data.fetch(:amount) order.save! end end + class UpdateTimePromotionDiscount + def call(event) + return unless event.data.fetch(:type) == Pricing::Discounts::TIME_PROMOTION_DISCOUNT + + order = Order.find_or_create_by!(order_uid: event.data.fetch(:order_id)) + order.time_promotion_discount = event.data.fetch(:amount) + order.save! + end + end + class UpdateOrderTotalValue def call(event) order = Order.find_or_create_by!(order_uid: event.data.fetch(:order_id)) { |order| order.state = "Draft" } @@ -90,10 +102,22 @@ def call(event) class RemoveDiscount def call(event) + return unless event.data.fetch(:type) == Pricing::Discounts::GENERAL_DISCOUNT + order = Order.find_by(order_uid: event.data.fetch(:order_id)) order.percentage_discount = nil order.save! end end + + class RemoveTimePromotionDiscount + def call(event) + return unless event.data.fetch(:type) == Pricing::Discounts::TIME_PROMOTION_DISCOUNT + + order = Order.find_by(order_uid: event.data.fetch(:order_id)) + order.time_promotion_discount = nil + order.save! + end + end end end diff --git a/rails_application/app/read_models/client_orders/rendering/show_order.rb b/rails_application/app/read_models/client_orders/rendering/show_order.rb index c0b242cf..748bd985 100644 --- a/rails_application/app/read_models/client_orders/rendering/show_order.rb +++ b/rails_application/app/read_models/client_orders/rendering/show_order.rb @@ -77,6 +77,7 @@ def footer_rows(order) tfoot class: "border-t-4" do before_discounts_row(order) if order.discounted_value != order.total_value general_discount_row(order) if order.percentage_discount + time_promotion_row(order) if order.time_promotion_discount total_row(order) end end @@ -95,6 +96,13 @@ def general_discount_row(order) end end + def time_promotion_row(order) + tr class: "border-t" do + td(class: "py-2", colspan: 3) { "Time promotion discount" } + td(class: "py-2 text-right") { "#{order.time_promotion_discount}%" } + end + end + def total_row(order) tr class: "border-t" do td(class: "py-2", colspan: 3) { "Total" } diff --git a/rails_application/db/migrate/20241129122521_add_time_promotion_discount_to_client_orders.rb b/rails_application/db/migrate/20241129122521_add_time_promotion_discount_to_client_orders.rb new file mode 100644 index 00000000..854c99f5 --- /dev/null +++ b/rails_application/db/migrate/20241129122521_add_time_promotion_discount_to_client_orders.rb @@ -0,0 +1,5 @@ +class AddTimePromotionDiscountToClientOrders < ActiveRecord::Migration[7.2] + def change + add_column :client_orders, :time_promotion_discount, :decimal, precision: 8, scale: 2 + end +end diff --git a/rails_application/db/schema.rb b/rails_application/db/schema.rb index 939d0106..bdb99f7a 100644 --- a/rails_application/db/schema.rb +++ b/rails_application/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_10_18_113912) do +ActiveRecord::Schema[7.2].define(version: 2024_11_29_122521) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -60,6 +60,7 @@ t.decimal "percentage_discount", precision: 8, scale: 2 t.decimal "total_value", precision: 8, scale: 2 t.decimal "discounted_value", precision: 8, scale: 2 + t.decimal "time_promotion_discount", precision: 8, scale: 2 end create_table "clients", force: :cascade do |t| diff --git a/rails_application/test/client_orders/discount_test.rb b/rails_application/test/client_orders/discount_test.rb index 0b5ba5e5..3d785a65 100644 --- a/rails_application/test/client_orders/discount_test.rb +++ b/rails_application/test/client_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 end def test_discount_changed @@ -35,14 +36,16 @@ 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 end - def test_remove_discount + def test_does_not_remove_time_promotion_when_removing_percentage_discount customer_id = SecureRandom.uuid product_id = SecureRandom.uuid order_id = SecureRandom.uuid customer_registered(customer_id) prepare_product(product_id) + create_active_time_promotion(50) item_added_to_basket(order_id, product_id) set_percentage_discount(order_id) @@ -50,12 +53,25 @@ def test_remove_discount order = Order.find_by(order_uid: order_id) assert_equal(50, order.total_value) - assert_equal(50, order.discounted_value) + assert_equal(25, order.discounted_value) assert_nil(order.percentage_discount) + assert_equal(50, order.time_promotion_discount) end private + def create_active_time_promotion(discount) + run_command( + Pricing::CreateTimePromotion.new( + time_promotion_id: SecureRandom.uuid, + discount: discount, + start_time: Time.current - 1, + end_time: Time.current + 1, + label: "Last Minute" + ) + ) + end + def remove_percentage_discount(order_id) run_command(Pricing::RemovePercentageDiscount.new(order_id: order_id)) end diff --git a/rails_application/test/client_orders/time_promotion_discount_test.rb b/rails_application/test/client_orders/time_promotion_discount_test.rb new file mode 100644 index 00000000..0dbf2b0d --- /dev/null +++ b/rails_application/test/client_orders/time_promotion_discount_test.rb @@ -0,0 +1,88 @@ +require "test_helper" + +module ClientOrders + class TimePromotionDiscountTest < InMemoryTestCase + cover "ClientOrders*" + + def test_time_promotion_set + customer_id = SecureRandom.uuid + product_id = SecureRandom.uuid + order_id = SecureRandom.uuid + customer_registered(customer_id) + prepare_product(product_id) + create_active_time_promotion(50) + item_added_to_basket(order_id, product_id) + + order = ClientOrders::Order.find_by(order_uid: order_id) + assert_equal 50, order.total_value + assert_equal 25, order.discounted_value + assert_equal 50, order.time_promotion_discount + assert_nil order.percentage_discount + end + + def test_does_not_remove_percentage_discount_when_removing_time_promotion + customer_id = SecureRandom.uuid + product_id = SecureRandom.uuid + order_id = SecureRandom.uuid + customer_registered(customer_id) + prepare_product(product_id) + create_active_time_promotion(50) + set_percentage_discount(order_id) + + travel_to Time.current + 1.day do + item_added_to_basket(order_id, product_id) + end + + order = ClientOrders::Order.find_by(order_uid: order_id) + assert_equal(50, order.total_value) + assert_equal(45, order.discounted_value) + assert_equal(10, order.percentage_discount) + assert_nil(order.time_promotion_discount) + end + + private + + def create_active_time_promotion(discount) + run_command( + Pricing::CreateTimePromotion.new( + time_promotion_id: SecureRandom.uuid, + discount: discount, + start_time: Time.current - 1, + end_time: Time.current + 1, + label: "Last Minute" + ) + ) + end + + def set_percentage_discount(order_id) + run_command(Pricing::SetPercentageDiscount.new(order_id: order_id, amount: 10)) + end + + def item_added_to_basket(order_id, product_id) + run_command(Pricing::AddPriceItem.new(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: "Async Remote" + ) + ) + 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 event_store + Rails.configuration.event_store + end + end +end diff --git a/rails_application/test/integration/client_orders_test.rb b/rails_application/test/integration/client_orders_test.rb index 71110470..5e8fcf39 100644 --- a/rails_application/test/integration/client_orders_test.rb +++ b/rails_application/test/integration/client_orders_test.rb @@ -197,6 +197,7 @@ def test_current_time_promotion_is_applied as_client_add_item_to_basket_for_order(product_id, order_id) as_client_submit_order_for_customer(order_id) + assert_select "tr td", "50.0%" assert_select "tr td", "$2.00" end diff --git a/rails_application/test/orders/discount_test.rb b/rails_application/test/orders/discount_test.rb index 00fae46b..baf08478 100644 --- a/rails_application/test/orders/discount_test.rb +++ b/rails_application/test/orders/discount_test.rb @@ -59,7 +59,7 @@ def test_remove_discount assert event_store.event_in_stream?(event_store.read.of_type([Pricing::PercentageDiscountRemoved]).last.event_id, "Orders$all") end - def test_does_not_remove_percentage_discount_when_time_promotion_reset + def test_does_not_remove_percentage_discount_when_removing_time_promotion customer_id = SecureRandom.uuid product_id = SecureRandom.uuid order_id = SecureRandom.uuid diff --git a/rails_application/test/orders/remove_time_promotion_discount_test.rb b/rails_application/test/orders/remove_time_promotion_discount_test.rb index b6fd2d29..366f3ab4 100644 --- a/rails_application/test/orders/remove_time_promotion_discount_test.rb +++ b/rails_application/test/orders/remove_time_promotion_discount_test.rb @@ -4,7 +4,7 @@ module Orders class RemoveTimePromotionDiscountTest < InMemoryTestCase cover "Orders*" - def test_resets_time_promotion_discount_value + def test_removes_time_promotion_discount_value customer_id = SecureRandom.uuid product_id = SecureRandom.uuid order_id = SecureRandom.uuid @@ -20,7 +20,7 @@ def test_resets_time_promotion_discount_value end end - def test_does_not_reset_time_promotion_when_general_discount_reset + def test_does_not_removes_time_promotion_when_removing_general_discount customer_id = SecureRandom.uuid product_id = SecureRandom.uuid order_id = SecureRandom.uuid