Skip to content

Commit

Permalink
Prevent empty order submission
Browse files Browse the repository at this point in the history
  • Loading branch information
marlena-b committed Aug 22, 2024
1 parent e779047 commit 9879123
Show file tree
Hide file tree
Showing 13 changed files with 156 additions and 29 deletions.
6 changes: 6 additions & 0 deletions ecommerce/ordering/lib/ordering/order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class Order
AlreadySubmitted = Class.new(InvalidState)
NotPlaced = Class.new(InvalidState)
OrderHasExpired = Class.new(InvalidState)
IsEmpty = Class.new(StandardError)

def initialize(id)
@id = id
Expand All @@ -16,6 +17,7 @@ def initialize(id)
def submit(order_number)
raise OrderHasExpired if @state.expired?
raise AlreadySubmitted unless @state.draft?
raise IsEmpty if @basket.empty?
apply OrderSubmitted.new(
data: {
order_id: @id,
Expand Down Expand Up @@ -111,6 +113,10 @@ def order_lines
def quantity(product_id)
order_lines[product_id]
end

def empty?
order_lines.empty?
end
end

class State
Expand Down
8 changes: 5 additions & 3 deletions ecommerce/ordering/test/order_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ def setup
@customer_id = SecureRandom.uuid
end

def test_order_lines_are_empty_after_adding_and_removing
def test_order_is_empty_after_adding_and_removing
order = Order.new(@order_id)
order.add_item(@product_id)
order.remove_item(@product_id)
order.submit(NumberGenerator.new.call)
assert_equal({}, order.unpublished_events.to_a.last.data[:order_lines])

assert_raises(Order::IsEmpty) do
order.submit(NumberGenerator.new.call)
end
end

def test_order_lines_with_the_same_product_twice
Expand Down
8 changes: 8 additions & 0 deletions ecommerce/ordering/test/submit_order_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,13 @@ def test_expired_order_could_not_be_created
act(SubmitOrder.new(order_id: aggregate_id))
end
end

def test_empty_order_cannot_be_submitted
aggregate_id = SecureRandom.uuid

assert_raises(Order::IsEmpty) do
act(SubmitOrder.new(order_id: aggregate_id))
end
end
end
end
11 changes: 7 additions & 4 deletions rails_application/app/controllers/client/orders_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ def new
end

def create
command_bus.(Ordering::SubmitOrder.new(order_id: params[:order_id]))
command_bus.(Crm::AssignCustomerToOrder.new(customer_id: cookies[:client_id], order_id: params[:order_id]))
redirect_to client_order_path(params[:order_id]),
notice: "Your order is being submitted"
ActiveRecord::Base.transaction do
command_bus.(Ordering::SubmitOrder.new(order_id: params[:order_id]))
command_bus.(Crm::AssignCustomerToOrder.new(customer_id: cookies[:client_id], order_id: params[:order_id]))
end
redirect_to client_order_path(params[:order_id]), notice: "Your order is being submitted"
rescue Ordering::Order::IsEmpty
redirect_to edit_client_order_path(params[:order_id]), alert: "You can't submit an empty order"
end

def show
Expand Down
2 changes: 2 additions & 0 deletions rails_application/app/controllers/orders_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ def remove_item
def create
ApplicationRecord.transaction { submit_order(params[:order_id], params[:customer_id]) }
redirect_to order_path(params[:order_id]), notice: "Your order is being submitted"
rescue Ordering::Order::IsEmpty
redirect_to edit_order_path(params[:order_id]), alert: "You can't submit an empty order"
rescue Crm::Customer::NotExists
redirect_to order_path(params[:order_id]), alert: "Order can not be submitted! Customer does not exist."
end
Expand Down
13 changes: 12 additions & 1 deletion rails_application/test/client_orders/order_cancelled_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def test_order_confirmed
customer_id = SecureRandom.uuid
order_id = SecureRandom.uuid
order_number = Ordering::FakeNumberGenerator::FAKE_NUMBER
product_id = SecureRandom.uuid

event_store.publish(Crm::CustomerRegistered.new(
data: {
Expand All @@ -23,6 +24,8 @@ def test_order_confirmed
}
))

create_product(product_id, "Async Remote", 30)
run_command(Ordering::AddItemToBasket.new(order_id: order_id, product_id: product_id))
run_command(Ordering::SubmitOrder.new(order_id: order_id, order_number: order_number))

event_store.publish(
Expand All @@ -39,5 +42,13 @@ def test_order_confirmed
assert_equal(order_number, orders.first.number)
assert_equal("Cancelled", orders.first.state)
end

private

def create_product(product_id, name, price)
run_command(ProductCatalog::RegisterProduct.new(product_id: product_id))
run_command(ProductCatalog::NameProduct.new(product_id: product_id, name: name))
run_command(Pricing::SetPrice.new(product_id: product_id, price: price))
end
end
end
end
11 changes: 11 additions & 0 deletions rails_application/test/client_orders/order_paid_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ def test_order_confirmed
customer_id = SecureRandom.uuid
order_id = SecureRandom.uuid
order_number = Ordering::FakeNumberGenerator::FAKE_NUMBER
product_id = SecureRandom.uuid

run_command(Crm::RegisterCustomer.new(customer_id: customer_id, name: "John Doe"))
create_product(product_id, "Async Remote", 30)
run_command(Ordering::AddItemToBasket.new(order_id: order_id, product_id: product_id))

event_store.publish(
Pricing::OrderTotalValueCalculated.new(
Expand Down Expand Up @@ -48,5 +51,13 @@ def test_order_confirmed
assert_equal(order_number, orders.first.number)
assert_equal("Paid", orders.first.state)
end

private

def create_product(product_id, name, price)
run_command(ProductCatalog::RegisterProduct.new(product_id: product_id))
run_command(ProductCatalog::NameProduct.new(product_id: product_id, name: name))
run_command(Pricing::SetPrice.new(product_id: product_id, price: price))
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,26 @@ def setup
Client.destroy_all
end

def test_update_orders_cummary
event_store = Rails.configuration.event_store
def test_update_orders_summary
customer_id = SecureRandom.uuid
other_customer_id = SecureRandom.uuid
product_id = SecureRandom.uuid
order_id = SecureRandom.uuid

register_product(product_id)
name_product(product_id, "Async Remote")
set_price_to_product(product_id, 3)
register_customer(other_customer_id)
register_customer(customer_id)
add_item_to_basket(order_id, product_id)
confirm_order(customer_id, order_id, 3)

customer = Client.find_by(uid: customer_id)
assert_equal 3.to_d, customer.paid_orders_summary

order_id = SecureRandom.uuid
add_item_to_basket(order_id, product_id)
add_item_to_basket(order_id, product_id)
confirm_order(customer_id, order_id, 6)

customer = Client.find_by(uid: customer_id)
Expand All @@ -36,6 +41,27 @@ def register_customer(customer_id)
run_command(Crm::RegisterCustomer.new(customer_id: customer_id, name: "John Doe"))
end

def register_product(product_id)
run_command(ProductCatalog::RegisterProduct.new(product_id: product_id))
end

def name_product(product_id, name)
run_command(
ProductCatalog::NameProduct.new(
product_id: product_id,
name: name
)
)
end

def set_price_to_product(product_id, price)
run_command(Pricing::SetPrice.new(product_id: product_id, price: price))
end

def add_item_to_basket(order_id, product_id)
run_command(Ordering::AddItemToBasket.new(order_id: order_id, product_id: product_id))
end

def confirm_order(customer_id, order_id, total_amount)
order_number = Ordering::FakeNumberGenerator::FAKE_NUMBER
event_store.publish(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,22 @@ def test_update_orders_summary
customer_id = SecureRandom.uuid
other_customer_id = SecureRandom.uuid
order_id = SecureRandom.uuid
product_id = SecureRandom.uuid

register_customer(other_customer_id)
register_customer(customer_id)
register_product(product_id)
name_product(product_id, "Async Remote")
set_price_to_product(product_id, 3)
add_item_to_basket(order_id, product_id)
confirm_order(customer_id, order_id, 3)

customer = Customer.find(customer_id)
assert_equal 3.to_d, customer.paid_orders_summary

order_id = SecureRandom.uuid
add_item_to_basket(order_id, product_id)
add_item_to_basket(order_id, product_id)
confirm_order(customer_id, order_id, 6)

customer = Customer.find(customer_id)
Expand All @@ -34,6 +41,22 @@ def register_customer(customer_id)
run_command(Crm::RegisterCustomer.new(customer_id: customer_id, name: "John Doe"))
end

def register_product(product_id)
run_command(ProductCatalog::RegisterProduct.new(product_id: product_id))
end

def name_product(product_id, name)
run_command(ProductCatalog::NameProduct.new(product_id: product_id, name: "Async Remote"))
end

def set_price_to_product(product_id, price)
run_command(Pricing::SetPrice.new(product_id: product_id, price: price))
end

def add_item_to_basket(order_id, product_id)
run_command(Ordering::AddItemToBasket.new(order_id: order_id, product_id: product_id))
end

def confirm_order(customer_id, order_id, total_amount)
order_number = Ordering::FakeNumberGenerator::FAKE_NUMBER
event_store.publish(
Expand Down
12 changes: 12 additions & 0 deletions rails_application/test/integration/client_orders_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,18 @@ def test_adding_product_which_is_not_available_in_requested_quantity
assert_equal "Product not available in requested quantity!", flash[:alert]
end

def test_empty_order_cannot_be_submitted
customer_id = register_customer("Customer Shop")

login(customer_id)
visit_client_orders

order_id = SecureRandom.uuid
as_client_submit_order_for_customer(order_id)

assert_select "#alert", "You can't submit an empty order"
end

private

def submit_order_for_customer(customer_id, order_id)
Expand Down
35 changes: 18 additions & 17 deletions rails_application/test/integration/orders_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,6 @@ def setup
add_available_vat_rate(10)
end

def test_submitting_empty_order
arkency_id = register_customer("Arkency")

get "/"
assert_select "h1", "Orders"
get "/orders/new"
follow_redirect!
assert_select "h1", "Order"
post "/orders",
params: {
"authenticity_token" => "[FILTERED]",
"order_id" => SecureRandom.uuid,
"customer_id" => arkency_id,
"commit" => "Submit order"
}
end

def test_happy_path
shopify_id = register_customer("Shopify")

Expand Down Expand Up @@ -202,6 +185,24 @@ def test_discount_is_applied_for_new_order
assert_select("td", "10.0%")
end

def test_empty_order_cannot_be_submitted
order_id = SecureRandom.uuid
shopify_id = register_customer("Shopify")

assert_no_changes -> { Orders::Order.count }, "You can't submit an empty order" do
post "/orders",
params: {
"authenticity_token" => "[FILTERED]",
"order_id" => order_id,
"customer_id" => shopify_id,
"commit" => "Submit order"
}
end
follow_redirect!

assert_select "#alert", "You can't submit an empty order"
end

private

def assert_remove_buttons_visible(async_remote_id, fearless_id, order_id)
Expand Down
13 changes: 12 additions & 1 deletion rails_application/test/orders/order_cancelled_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def test_cancel_confirmed_order
customer_id = SecureRandom.uuid
order_id = SecureRandom.uuid
order_number = Ordering::FakeNumberGenerator::FAKE_NUMBER
product_id = SecureRandom.uuid

event_store.publish(Crm::CustomerRegistered.new(
data: {
Expand All @@ -23,6 +24,8 @@ def test_cancel_confirmed_order
}
))

create_product(product_id, "Async Remote", 30)
run_command(Ordering::AddItemToBasket.new(order_id: order_id, product_id: product_id))
run_command(Ordering::SubmitOrder.new(order_id: order_id, order_number: order_number))

order_cancelled = Fulfillment::OrderCancelled.new(
Expand All @@ -40,5 +43,13 @@ def test_cancel_confirmed_order
assert_equal("Cancelled", orders.first.state)
assert event_store.event_in_stream?(order_cancelled.event_id, "Orders$all")
end

private

def create_product(product_id, name, price)
run_command(ProductCatalog::RegisterProduct.new(product_id: product_id))
run_command(ProductCatalog::NameProduct.new(product_id: product_id, name: name))
run_command(Pricing::SetPrice.new(product_id: product_id, price: price))
end
end
end
end
13 changes: 12 additions & 1 deletion rails_application/test/orders/order_paid_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ def test_order_confirmed
customer_id = SecureRandom.uuid
order_id = SecureRandom.uuid
order_number = Ordering::FakeNumberGenerator::FAKE_NUMBER
product_id = SecureRandom.uuid

create_product(product_id, "Async Remote", 10)
run_command(Crm::RegisterCustomer.new(customer_id: customer_id, name: "John Doe"))
run_command(Ordering::AddItemToBasket.new(order_id: order_id, product_id: product_id))
run_command(Ordering::SubmitOrder.new(order_id: order_id, order_number: order_number))
run_command(
Crm::AssignCustomerToOrder.new(customer_id: customer_id, order_id: order_id)
Expand All @@ -37,5 +40,13 @@ def test_order_confirmed
assert_equal("Paid", orders.first.state)
assert event_store.event_in_stream?(order_confirmed.event_id, "Orders$all")
end

private

def create_product(product_id, name, price)
run_command(ProductCatalog::RegisterProduct.new(product_id: product_id))
run_command(ProductCatalog::NameProduct.new(product_id: product_id, name: name))
run_command(Pricing::SetPrice.new(product_id: product_id, price: price))
end
end
end
end

0 comments on commit 9879123

Please sign in to comment.