Skip to content

Commit

Permalink
Display out of stock badge for products on order creation page
Browse files Browse the repository at this point in the history
  • Loading branch information
marlena-b committed Sep 3, 2024
1 parent 690d65d commit fdede5b
Show file tree
Hide file tree
Showing 15 changed files with 180 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ def value
end
end

class Product < ApplicationRecord
self.table_name = "client_order_products"

def unavailable?
available && available <= 0
end
end

class Configuration
def call(event_store)
event_store.subscribe(ExpireOrder, to: [Ordering::OrderExpired])
Expand All @@ -43,6 +51,7 @@ def call(event_store)
event_store.subscribe(ChangeProductName, to: [ProductCatalog::ProductNamed])
event_store.subscribe(ChangeProductPrice, to: [Pricing::PriceSet])
event_store.subscribe(RegisterProduct, to: [ProductCatalog::ProductRegistered])
event_store.subscribe(UpdateProductAvailability, to: [Inventory::AvailabilityChanged])
event_store.subscribe(UpdateDiscount, to: [Pricing::PercentageDiscountSet, Pricing::PercentageDiscountChanged])
event_store.subscribe(ResetDiscount, to: [Pricing::PercentageDiscountReset])
event_store.subscribe(UpdateOrderTotalValue, to: [Pricing::OrderTotalValueCalculated])
Expand Down
5 changes: 0 additions & 5 deletions rails_application/app/read_models/client_orders/product.rb

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module ClientOrders
class UpdateProductAvailability
def call(event)
Product.find_by(uid: event.data.fetch(:product_id)).update(available: event.data.fetch(:available))
end
end
end
5 changes: 5 additions & 0 deletions rails_application/app/read_models/products/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ def future_prices_calendar
current_prices_calendar.select { |entry| entry[:valid_since] > Time.current }
end

def unavailable?
available && available <= 0
end

private

def last_price_before(time)
Expand Down Expand Up @@ -49,6 +53,7 @@ def call
@read_model.subscribe_copy(ProductCatalog::ProductNamed, :name)
@read_model.subscribe_copy(Inventory::StockLevelChanged, :stock_level)
@read_model.subscribe_copy(Taxes::VatRateSet, [:vat_rate, :code])
@read_model.subscribe_copy(Inventory::AvailabilityChanged, :available)
@event_store.subscribe(RefreshFuturePricesCalendar, to: [Pricing::PriceSet])
end
end
Expand Down
6 changes: 6 additions & 0 deletions rails_application/app/views/client/orders/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<thead>
<tr class="border-b">
<th class="text-left py-2">Product</th>
<th class="text-left py-2"></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>
Expand All @@ -14,6 +15,11 @@
<tr class="border-b">
<% order_line = @order_lines&.find{|order_line| order_line.product_id == product.uid} %>
<td class="py-2"><%= product.name %></td>
<td class="py-2">
<% if product.unavailable? %>
<span class="rounded-lg bg-yellow-400 text-yellow-900 px-2 py-0.5">out of stock</span>
<% end %>
</td>
<td class="py-2" id="<%= "client_orders_#{product.uid}_product_quantity" %>"><%= order_line.try(&:product_quantity) || 0 %></td>
<td class="py-2"><%= number_to_currency(product.price) %></td>
<td class="py-2" id="<%= "client_orders_#{product.uid}_value" %>"><%= number_to_currency(order_line.try(&:value)) %></td>
Expand Down
6 changes: 6 additions & 0 deletions rails_application/app/views/orders/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<thead>
<tr class="border-b">
<th class="text-left py-2">Product</th>
<th class="text-left py-2"></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>
Expand All @@ -41,6 +42,11 @@
<tr class="border-b">
<% order_line = @order_lines.find{|order_line| order_line.product_id == product.id} %>
<td class="py-2"><%= product.name %></td>
<td class="py-2">
<% if product.unavailable? %>
<span class="rounded-lg bg-yellow-400 text-yellow-900 px-2 py-0.5">out of stock</span>
<% end %>
</td>
<td class="py-2" id="<%= "orders_order_#{product.id}_quantity" %>"><%= order_line.try(&:quantity) || 0 %></td>
<td class="py-2"><%= number_to_currency(product.price) %></td>
<td class="py-2" id="<%= "orders_order_#{product.id}_value" %>"><%= number_to_currency(order_line.try(&:value)) %></td>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddAvailableToProducts < ActiveRecord::Migration[7.2]
def change
add_column :products, :available, :integer
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddAvailableToClientOrderProducts < ActiveRecord::Migration[7.2]
def change
add_column :client_order_products, :available, :integer
end
end
4 changes: 3 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_08_12_080357) do
ActiveRecord::Schema[7.2].define(version: 2024_08_27_090619) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
enable_extension "plpgsql"
Expand Down Expand Up @@ -46,6 +46,7 @@
t.uuid "uid", null: false
t.string "name"
t.decimal "price", precision: 8, scale: 2
t.integer "available"
end

create_table "client_orders", force: :cascade do |t|
Expand Down Expand Up @@ -182,6 +183,7 @@
t.datetime "registered_at", precision: nil
t.string "vat_rate_code"
t.text "current_prices_calendar"
t.integer "available"
end

create_table "public_offer_products", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
Expand Down
21 changes: 21 additions & 0 deletions rails_application/test/client_orders/product_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require "test_helper"

module ClientOrders
class ProductTest < InMemoryTestCase
cover "ClientOrders*"

def test_unavailable
product = Product.new(available: nil)
refute product.unavailable?

product = Product.new(available: 0)
assert product.unavailable?

product = Product.new(available: 1)
refute product.unavailable?

product = Product.new(available: -1)
assert product.unavailable?
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require "test_helper"

module ClientOrders
class UpdateProductAvailabilityTest < InMemoryTestCase
cover "ClientOrders*"

def test_reflects_change
product_id = prepare_product
other_product_id = prepare_product

supply_product(product_id, 5)

assert_equal 5, Product.find_by_uid(product_id).available
assert_nil Product.find_by_uid(other_product_id).available
end

private

def prepare_product
product_id = SecureRandom.uuid
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))

product_id
end

def supply_product(product_id, quantity)
run_command(Inventory::Supply.new(product_id: product_id, quantity: quantity))
end
end
end
19 changes: 19 additions & 0 deletions rails_application/test/integration/client_orders_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,25 @@ def test_empty_order_cannot_be_submitted
assert_select "#alert", "You can't submit an empty order"
end

def test_shows_out_of_stock_badge
shopify_id = register_customer("Shopify")
order_id = SecureRandom.uuid
async_remote_id = register_product("Async Remote", 39, 10)

supply_product(async_remote_id, 1)
login(shopify_id)
get "/client_orders/new"

assert_select "td span", text: "out of stock", count: 0

as_client_add_item_to_basket_for_order(async_remote_id, order_id)
as_client_submit_order_for_customer(order_id)

get "/client_orders/new"

assert_select "td span", "out of stock"
end

private

def submit_order_for_customer(customer_id, order_id)
Expand Down
27 changes: 27 additions & 0 deletions rails_application/test/integration/orders_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,33 @@ def test_order_cannot_be_submitted_with_out_of_stock_product
assert_equal "Order can not be submitted! Fearless Refactoring not available in requested quantity!", flash[:alert]
end

def test_shows_out_of_stock_badge
shopify_id = register_customer("Shopify")
order_id = SecureRandom.uuid
async_remote_id = register_product("Async Remote", 39, 10)

supply_product(async_remote_id, 1)

get "/orders/new"
follow_redirect!

assert_select "td span", text: "out of stock", count: 0

post "/orders/#{order_id}/add_item?product_id=#{async_remote_id}"
post "/orders",
params: {
"authenticity_token" => "[FILTERED]",
"order_id" => order_id,
"customer_id" => shopify_id,
"commit" => "Submit order"
}

get "/orders/new"
follow_redirect!

assert_select "td span", "out of stock"
end

private

def assert_remove_buttons_visible(async_remote_id, fearless_id, order_id)
Expand Down
5 changes: 5 additions & 0 deletions rails_application/test/integration/supplies_test.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
require "test_helper"

class SuppliesTest < InMemoryRESIntegrationTestCase
def setup
super
add_available_vat_rate(10)
end

def test_happy_path
product_id = register_product("Async Remote", 100, 10)

Expand Down
21 changes: 21 additions & 0 deletions rails_application/test/products/product_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require "test_helper"

module Products
class ProductTest < InMemoryTestCase
cover "Products*"

def test_unavailable
product = Product.new(available: nil)
refute product.unavailable?

product = Product.new(available: 0)
assert product.unavailable?

product = Product.new(available: 1)
refute product.unavailable?

product = Product.new(available: -1)
assert product.unavailable?
end
end
end

0 comments on commit fdede5b

Please sign in to comment.