Skip to content

Commit

Permalink
Estime final price of an order for a client
Browse files Browse the repository at this point in the history
  • Loading branch information
marlena-b committed Nov 11, 2024
1 parent ca5941d commit 18b3ca0
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 23 deletions.
16 changes: 16 additions & 0 deletions rails_application/app/read_models/client_orders/order_handlers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ def call(event)
order.discounted_value = event.data.fetch(:discounted_amount)
order.total_value = event.data.fetch(:total_amount)
order.save!

broadcast_update(order.order_uid, "total_value", number_to_currency(order.total_value))
broadcast_update(order.order_uid, "discounted_value", number_to_currency(order.discounted_value))
end

private

def broadcast_update(order_id, target, content)
Turbo::StreamsChannel.broadcast_update_to(
"client_orders_#{order_id}",
target: "client_orders_#{order_id}_#{target}",
html: content)
end

def number_to_currency(number)
ActiveSupport::NumberHelper.number_to_currency(number)
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,32 @@ class EditOrder < Arbre::Component
include ActionView::Helpers::UrlHelper

def self.build(view_context, order_id)
order = ClientOrders::Order.find_or_initialize_by(order_uid: order_id) do |order|
order.total_value = 0
order.discounted_value = 0
end
order_lines = ClientOrders::OrderLine.where(order_uid: order_id)
products = ClientOrders::Product.all
new(Arbre::Context.new(nil, view_context)).build(order_id, order_lines, products)
time_promotions = TimePromotions::TimePromotion.current
new(Arbre::Context.new(nil, view_context)).build(order, order_lines, products, time_promotions)
end

def build(order_id, order_lines, products, attributes = {})
def build(order, order_lines, products, time_promotions, attributes = {})
super(attributes)
div do
products_table(order_id, products, order_lines)
coupon_form(order_id)
submit_form(order_id)
products_table(order, products, order_lines, time_promotions)
coupon_form(order)
submit_form(order)
end
end

private

def products_table(order_id, products, order_lines)
def products_table(order, products, order_lines, time_promotions)
table class: "w-full" do
headers_row
tbody do
text_node turbo_stream_from "client_orders_#{order_id}"
products.each do |product|
product_row(order_id, product, order_lines)
end
end
products_rows(order, products, order_lines)
footer_rows(order, time_promotions)
end
end

Expand All @@ -46,16 +47,34 @@ def headers_row
end
end

def product_row(order_id, product, order_lines)
def products_rows(order, products, order_lines)
tbody do
text_node turbo_stream_from "client_orders_#{order.order_uid}"
products.each do |product|
product_row(order, product, order_lines)
end
end
end

def product_row(order, product, order_lines)
order_line = order_lines&.find { |order_line| order_line.product_id == product.uid }
tr class: "border-b" do
td(class: "py-2") { product.name }
td(class: "py-2") { out_of_stock_badge unless product.available? }
td(class: "py-2", id: "client_orders_#{product.uid}_product_quantity") { order_line.try(&:product_quantity) || 0 }
td(class: "py-2") { number_to_currency(product.price) }
td(class: "py-2", id: "client_orders_#{product.uid}_value") { number_to_currency(order_line.try(&:value)) }
td(class: "py-2 text-right") { add_item_button(order_id, product.uid) }
td(class: "py-2 text-right", id: "client_orders_#{product.uid}_remove_item_button") { remove_item_button(order_id, product.uid) if order_line }
td(class: "py-2", id: "client_orders_#{product.uid}_value") { number_to_currency(order_line.try(&:value)) || "$0.00" }
td(class: "py-2 text-right") { add_item_button(order.order_uid, product.uid) }
td(class: "py-2 text-right", id: "client_orders_#{product.uid}_remove_item_button") { remove_item_button(order, product.uid) if order_line }
end
end

def footer_rows(order, time_promotions)
tfoot class:"border-t-4" do
before_discounts_row(order) if order.percentage_discount || time_promotions.any?
coupon_discount_row(order) if order.percentage_discount
time_promotions_rows(time_promotions)
total_row(order)
end
end

Expand All @@ -67,12 +86,42 @@ def add_item_button(order_id, product_id)
button_to "Add", add_item_client_order_path(id: order_id, product_id: product_id), class: "hover:underline text-blue-500"
end

def remove_item_button(order_id, product_id)
button_to "Remove", remove_item_client_order_path(id: order_id, product_id: product_id), class: "hover:underline text-blue-500"
def remove_item_button(order, product_id)
button_to "Remove", remove_item_client_order_path(id: order.order_uid, product_id: product_id), class: "hover:underline text-blue-500"
end

def before_discounts_row(order)
tr(class: "border-t") do
td(class: "py-2", colspan: 4) { "Before discounts" }
td(class: "py-2", id: "client_orders_#{order.order_uid}_total_value") { number_to_currency(order.total_value) }
end
end

def coupon_discount_row(order)
tr(class: "border-t") do
td(class: "py-2", colspan: 4) { "Coupon discount" }
td(class: "py-2", id: "client_orders_#{order.order_uid}_percentage_discount") { "#{order.percentage_discount}%" }
end
end

def time_promotions_rows(time_promotions)
time_promotions.each do |time_promotion|
tr(class: "border-t") do
td(class: "py-2", colspan: 4) { "Promotion: #{time_promotion.label} (if you buy before #{time_promotion.end_time})"}
td(class: "py-2") { "#{time_promotion.discount}%" }
end
end
end

def total_row(order)
tr(class: "border-t") do
td(class: "py-2", colspan: 4) { "Total" }
td(class: "py-2 font-bold", id: "client_orders_#{order.order_uid}_discounted_value") { number_to_currency(order.discounted_value) }
end
end

def coupon_form(order_id)
form(action: use_coupon_client_order_path(id: order_id), method: :post, class: "inline-flex gap-4 mt-8") do
def coupon_form(order)
form(action: use_coupon_client_order_path(id: order.order_uid), method: :post, class: "inline-flex gap-4 mt-8") do
input(
id: "coupon_code",
type: :text,
Expand All @@ -84,9 +133,9 @@ def coupon_form(order_id)
end
end

def submit_form(order_id)
def submit_form(order)
form(id: "form", action: client_orders_path, method: :post) do
input(type: :hidden, name: :order_id, value: order_id)
input(type: :hidden, name: :order_id, value: order.order_uid)
div(class: "mt-8") do
input type: :submit, value: "Create Order", class: "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

module ClientOrders
class UpdateOrderTotalValueTest < InMemoryTestCase
include ActionCable::TestHelper
cover "ClientOrders*"

def test_order_created_has_draft_state
Expand All @@ -17,6 +18,28 @@ def test_order_created_has_draft_state
assert_equal "Draft", order.state
end

def test_broadcasts
order_id = SecureRandom.uuid
event_store.publish(Pricing::OrderTotalValueCalculated.new(data: { order_id: order_id, discounted_amount: 0, total_amount: 10 }))

assert_broadcast_on(
"client_orders_#{order_id}",
turbo_stream_action_tag(
action: "update",
target: "client_orders_#{order_id}_total_value",
template: "$10.00"
)
)
assert_broadcast_on(
"client_orders_#{order_id}",
turbo_stream_action_tag(
action: "update",
target: "client_orders_#{order_id}_discounted_value",
template: "$0.00"
)
)
end

private

def item_added_to_basket(order_id, product_id)
Expand Down Expand Up @@ -45,6 +68,9 @@ def customer_registered(customer_id)
def event_store
Rails.configuration.event_store
end

def turbo_stream_action_tag(action:, target:, template:)
"<turbo-stream action=\"#{action}\" target=\"#{target}\"><template>#{template}</template></turbo-stream>"
end
end
end

30 changes: 30 additions & 0 deletions rails_application/test/integration/client_orders_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,23 @@ def test_using_coupon_twice
assert_select "#alert", "Coupon already used!"
end

def test_shows_estimated_final_price_including_discounts
customer_id = register_customer("Customer Shop")
product_id = register_product("Fearless Refactoring", 4, 10)
register_coupon("Coupon", "coupon10", 10)
time_promotion_end_time = Time.current + 1.day
create_current_time_promotion(discount: 50, end_time: time_promotion_end_time)

login(customer_id)
visit_client_orders

order_id = SecureRandom.uuid
as_client_add_item_to_basket_for_order(product_id, order_id)
as_client_use_coupon(order_id, "COUPON10")

assert_order_final_price_with_discounts("$4.00", "10.0%", "50%", "$1.60", time_promotion_end_time)
end

private

def submit_order_for_customer(customer_id, order_id)
Expand Down Expand Up @@ -304,6 +321,19 @@ def assert_orders_summary(summary)
end
end

def assert_order_final_price_with_discounts(before_discounts, coupon, time_promotion, after_discounts, time_promotion_end_time)
assert_select "tr" do
assert_select "td", "Before discounts"
assert_select "td", before_discounts
assert_select "td", "Coupon discount"
assert_select "td", coupon
assert_select "td", "Promotion: Last Minute (if you buy before #{time_promotion_end_time})"
assert_select "td", time_promotion
assert_select "td", "Total"
assert_select "td", after_discounts
end
end

def update_price(product_id, new_price)
patch "/products/#{product_id}",
params: {
Expand Down

0 comments on commit 18b3ca0

Please sign in to comment.