From f91433eb711e3196b323b0e2e84fe835c353efa8 Mon Sep 17 00:00:00 2001 From: marlena-b Date: Mon, 9 Dec 2024 18:58:35 +0100 Subject: [PATCH] Add new refund form and read models --- .../app/controllers/refunds_controller.rb | 7 +++ .../app/read_models/refunds/configuration.rb | 20 +++++++++ .../app/views/orders/show.html.erb | 4 ++ .../app/views/refunds/new.html.erb | 43 +++++++++++++++++++ rails_application/config/routes.rb | 1 + .../migrate/20241209100544_create_refunds.rb | 12 ++++++ .../20241209102208_create_refund_items.rb | 12 ++++++ rails_application/db/schema.rb | 20 ++++++++- rails_application/lib/configuration.rb | 5 +++ .../test/integration/refunds_test.rb | 38 ++++++++++++++++ 10 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 rails_application/app/controllers/refunds_controller.rb create mode 100644 rails_application/app/read_models/refunds/configuration.rb create mode 100644 rails_application/app/views/refunds/new.html.erb create mode 100644 rails_application/db/migrate/20241209100544_create_refunds.rb create mode 100644 rails_application/db/migrate/20241209102208_create_refund_items.rb create mode 100644 rails_application/test/integration/refunds_test.rb diff --git a/rails_application/app/controllers/refunds_controller.rb b/rails_application/app/controllers/refunds_controller.rb new file mode 100644 index 00000000..2638a976 --- /dev/null +++ b/rails_application/app/controllers/refunds_controller.rb @@ -0,0 +1,7 @@ +class RefundsController < ApplicationController + def new + @order = Orders::Order.find_by_uid(params[:order_id]) + @refund = Refunds::Refund.new + @order_lines = Orders::OrderLine.where(order_uid: params[:order_id]) + end +end diff --git a/rails_application/app/read_models/refunds/configuration.rb b/rails_application/app/read_models/refunds/configuration.rb new file mode 100644 index 00000000..271a8405 --- /dev/null +++ b/rails_application/app/read_models/refunds/configuration.rb @@ -0,0 +1,20 @@ +module Refunds + class Refund < ApplicationRecord + self.table_name = "refunds" + + has_many :refund_items, + class_name: "Refunds::RefundItem", + foreign_key: :order_uid, + primary_key: :uid + end + + class RefundItem < ApplicationRecord + self.table_name = "refund_items" + end + + class Configuration + def call(event_store) + @event_store = event_store + end + end +end diff --git a/rails_application/app/views/orders/show.html.erb b/rails_application/app/views/orders/show.html.erb index cf0ccd3b..979967ca 100644 --- a/rails_application/app/views/orders/show.html.erb +++ b/rails_application/app/views/orders/show.html.erb @@ -23,6 +23,10 @@ <%= button_to("Pay", pay_order_path(@order.uid), class: "mr-3 ml-3 inline-flex items-center px-4 py-2 border rounded-md shadow-sm text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 border-transparent text-white bg-blue-600 hover:bg-blue-700") %> <% end %> + <% if @order.state == "Submitted" %> + <%= link_to("Refund", new_order_refund_path(order_id: @order.uid), class: "mr-3 inline-flex items-center px-4 py-2 border rounded-md shadow-sm text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-50 border-gray-300 text-gray-700 bg-white hover:bg-gray-50") %> + <% end %> + <% if (@order.state == "Submitted") %> <%= button_to("Cancel Order", cancel_order_path(@order.uid), class: "inline-flex items-center px-4 py-2 border rounded-md shadow-sm text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-50 border-gray-300 text-gray-700 bg-white hover:bg-gray-50") %> <% end %> diff --git a/rails_application/app/views/refunds/new.html.erb b/rails_application/app/views/refunds/new.html.erb new file mode 100644 index 00000000..c9cf843b --- /dev/null +++ b/rails_application/app/views/refunds/new.html.erb @@ -0,0 +1,43 @@ +<% content_for(:header) do %> + Refund for Order <%= @order.number %> +<% end %> + +<% content_for(:actions) do %> + <%= secondary_action_button do %> + <%= link_to 'Back', orders_path %> + <% end %> + + <%= primary_form_action_button do %> + Submit Refund + <% end %> +<% end %> + + + + + + + + + + + + + <% @order_lines.each do |order_line| %> + + + + + + + + + <% end %> + + + + + + + +
ProductQuantityPriceValue
<%= order_line.product_name %>0 / <%= order_line.quantity %><%= number_to_currency(order_line.price) %><%= number_to_currency(order_line.value) %><%= button_to "Add", "#", class: "hover:underline text-blue-500" %><%= button_to("Remove", "#", class: "hover:underline text-blue-500") %>
Total
diff --git a/rails_application/config/routes.rb b/rails_application/config/routes.rb index e52f6d35..079b59b5 100644 --- a/rails_application/config/routes.rb +++ b/rails_application/config/routes.rb @@ -17,6 +17,7 @@ resource :shipping_address, only: [:edit, :update] resource :billing_address, only: [:edit, :update] resource :invoice, only: [:create] + resources :refunds, only: [:new] end resources :shipments, only: [:index, :show] diff --git a/rails_application/db/migrate/20241209100544_create_refunds.rb b/rails_application/db/migrate/20241209100544_create_refunds.rb new file mode 100644 index 00000000..5710d274 --- /dev/null +++ b/rails_application/db/migrate/20241209100544_create_refunds.rb @@ -0,0 +1,12 @@ +class CreateRefunds < ActiveRecord::Migration[7.2] + def change + create_table :refunds do |t| + t.uuid :uid + t.uuid :order_uid + t.string :status + t.decimal :total_value, precision: 8, scale: 2 + + t.timestamps + end + end +end diff --git a/rails_application/db/migrate/20241209102208_create_refund_items.rb b/rails_application/db/migrate/20241209102208_create_refund_items.rb new file mode 100644 index 00000000..f75ce602 --- /dev/null +++ b/rails_application/db/migrate/20241209102208_create_refund_items.rb @@ -0,0 +1,12 @@ +class CreateRefundItems < ActiveRecord::Migration[7.2] + def change + create_table :refund_items do |t| + t.uuid :refund_uid + t.uuid :product_uid + t.integer :quantity + t.decimal :price, precision: 8, scale: 2 + + t.timestamps + end + end +end diff --git a/rails_application/db/schema.rb b/rails_application/db/schema.rb index 939d0106..a80e1193 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_12_09_102208) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -194,6 +194,24 @@ t.decimal "lowest_recent_price", precision: 8, scale: 2 end + create_table "refund_items", force: :cascade do |t| + t.uuid "refund_uid" + t.uuid "product_uid" + t.integer "quantity" + t.decimal "price", precision: 8, scale: 2 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "refunds", force: :cascade do |t| + t.uuid "uid" + t.uuid "order_uid" + t.string "status" + t.decimal "total_value", precision: 8, scale: 2 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "shipment_items", force: :cascade do |t| t.bigint "shipment_id", null: false t.string "product_name", null: false diff --git a/rails_application/lib/configuration.rb b/rails_application/lib/configuration.rb index 512be070..60ed8722 100644 --- a/rails_application/lib/configuration.rb +++ b/rails_application/lib/configuration.rb @@ -17,6 +17,7 @@ def call(event_store, command_bus) enable_availability_read_model(event_store) enable_authentication_read_model(event_store) enable_vat_rates_read_model(event_store) + enable_refunds_read_model(event_store) Ecommerce::Configuration.new( number_generator: Rails.configuration.number_generator, @@ -81,4 +82,8 @@ def enable_authentication_read_model(event_store) def enable_vat_rates_read_model(event_store) VatRates::Configuration.new.call(event_store) end + + def enable_refunds_read_model(event_store) + Refunds::Configuration.new.call(event_store) + end end diff --git a/rails_application/test/integration/refunds_test.rb b/rails_application/test/integration/refunds_test.rb new file mode 100644 index 00000000..816a1b4b --- /dev/null +++ b/rails_application/test/integration/refunds_test.rb @@ -0,0 +1,38 @@ +require "test_helper" + +class RefundsTest < InMemoryRESIntegrationTestCase + def setup + super + add_available_vat_rate(10) + end + + def test_happy_path + shopify_id = register_customer("Shopify") + order_id = SecureRandom.uuid + async_remote_id = register_product("Async Remote", 39, 10) + fearless_id = register_product("Fearless Refactoring", 49, 10) + + add_product_to_basket(order_id, async_remote_id) + add_product_to_basket(order_id, fearless_id) + add_product_to_basket(order_id, fearless_id) + submit_order(shopify_id, order_id) + + get "/orders/#{order_id}" + + assert_select("a", "Refund") + + get "/orders/#{order_id}/refunds/new" + + assert_order_line_row(async_remote_id, "Async Remote", 1) + assert_order_line_row(fearless_id, "Fearless Refactoring", 2) + end + + private + + def assert_order_line_row(product_id, product_name, quantity) + assert_select("#order_line_product_#{product_id}") do + assert_select("td", product_name) + assert_select("td", "0 / #{quantity}") + end + end +end