Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new refund form and read models #424

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions rails_application/app/controllers/refunds_controller.rb
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions rails_application/app/read_models/refunds/configuration.rb
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions rails_application/app/views/orders/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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 %>
Expand Down
43 changes: 43 additions & 0 deletions rails_application/app/views/refunds/new.html.erb
Original file line number Diff line number Diff line change
@@ -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 %>

<table class="w-full">
<thead>
<tr class="border-b">
<th class="text-left py-2">Product</th>
<th class="text-left py-2">Quantity</th>
<th class="text-left py-2">Price</th>
<th class="text-left py-2" colspan="3">Value</th>
</tr>
</thead>

<tbody>
<% @order_lines.each do |order_line| %>
<tr class="border-b" id="order_line_product_<%= order_line.product_id %>">
<td class="py-2"><%= order_line.product_name %></td>
<td class="py-2">0 / <%= order_line.quantity %></td>
<td class="py-2"><%= number_to_currency(order_line.price) %></td>
<td class="py-2"><%= number_to_currency(order_line.value) %></td>
<td class="py-2"><%= button_to "Add", "#", class: "hover:underline text-blue-500" %></td>
<td class="py-2 text-right"><%= button_to("Remove", "#", class: "hover:underline text-blue-500") %></td>
</tr>
<% end %>
</tbody>
<tfoot class="border-t-4">
<tr class="border-t">
<td class="py-2" colspan="3">Total</td>
<td class="py-2 font-bold"></td></td>
</tr>
</tfoot>
</table>
1 change: 1 addition & 0 deletions rails_application/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
12 changes: 12 additions & 0 deletions rails_application/db/migrate/20241209100544_create_refunds.rb
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions rails_application/db/migrate/20241209102208_create_refund_items.rb
Original file line number Diff line number Diff line change
@@ -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
20 changes: 19 additions & 1 deletion rails_application/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions rails_application/lib/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
38 changes: 38 additions & 0 deletions rails_application/test/integration/refunds_test.rb
Original file line number Diff line number Diff line change
@@ -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