Skip to content

Commit

Permalink
Add the adjustments index page
Browse files Browse the repository at this point in the history
  • Loading branch information
elia committed Jan 9, 2024
1 parent 8372a98 commit b5e21ff
Show file tree
Hide file tree
Showing 9 changed files with 407 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
# frozen_string_literal: true

class SolidusAdmin::Orders::Show::Adjustments::Index::Component < SolidusAdmin::UI::Pages::Index::Component
def model_class
Spree::Adjustment
end

def back_url
solidus_admin.order_path(@order)
end

def title
t(".title", number: @order.number)
end

NBSP = "&nbsp;".html_safe

def initialize(order:, adjustments:)
@order = order
@adjustments = adjustments
@page = GearedPagination::Recordset.new(adjustments, per_page: adjustments.size).page(1)
end

def batch_actions
[
{
display_name: t(".actions.lock"),
action: solidus_admin.lock_order_adjustments_path(@order),
method: :put,
icon: "lock-line"
},
{
display_name: t(".actions.unlock"),
action: solidus_admin.unlock_order_adjustments_path(@order),
method: :put,
icon: "lock-unlock-line"
},
{
display_name: t(".actions.delete"),
action: spree.admin_order_adjustment_path(@order, '[]'),
method: :delete,
icon: "delete-bin-7-line"
},
]
end

def search_key
:label_cont
end

def search_url
solidus_admin.order_adjustments_path(@order)
end

def sidebar
safe_join [
render(component('ui/panel').new(title: t(".totals.adjustable")) { |panel|
panel.with_section {
render component('ui/details_list').new(items: @adjustments.group(:adjustable_type).sum(:amount).map { |type, amount|
{ label: (type ? type.constantize.model_name.human : tag.em(t('.none'))), value: Spree::Money.new(amount).to_html }
}.sort_by { _1[:label] })
}
}),
render(component('ui/panel').new(title: t(".totals.source")) { |panel|
panel.with_section {
render component('ui/details_list').new(items: @adjustments.group(:source_type).sum(:amount).map { |type, amount|
{ label: (type ? type.constantize.model_name.human : tag.em(t('.none'))), value: Spree::Money.new(amount).to_html }
}.sort_by { _1[:label] })
}
}),
]
end

def columns
[
{
header: :state,
wrap: true,
col: { class: 'w-[calc(5rem+2rem+2.5rem+1px)]' },
data: ->(adjustment) {
if adjustment.finalized?
icon = 'lock-fill'
title = t(".state.locked")
else
icon = 'lock-unlock-line'
title = t(".state.unlocked")
end
icon_tag(icon, class: "w-5 h-5 align-middle") + tag.span(title)
}
},
{
header: :adjustable,
col: { class: 'w-56' },
data: ->(adjustment) {
tag.figure(safe_join([
render(component("ui/thumbnail").for(adjustment.adjustable, class: "basis-10")),
figcaption_for_adjustable(adjustment),
]), class: "flex items-center gap-2")
}
},
{
header: :source,
col: { class: "w-56" },
data: ->(adjustment) {
tag.figure(safe_join([
figcaption_for_source(adjustment),
]), class: "flex items-center gap-2")
}
},
{
header: :amount,
col: { class: 'w-24' },
data: ->(adjustment) { tag.span adjustment.display_amount.to_html, class: "grow text-right whitespace-nowrap" }
},
{
header: tag.span(t(".actions.title"), class: 'sr-only'),
col: { class: 'w-24' },
wrap: false,
data: ->(adjustment) do
actions = []

unless adjustment.source
actions << link_to(
t(".actions.edit"),
spree.edit_admin_order_adjustment_path(@order, adjustment),
class: 'body-link',
)
end

if adjustment.finalized?
actions << link_to(
t(".actions.unlock"),
solidus_admin.unlock_order_adjustments_path(@order, id: adjustment),
"data-turbo-method": :put,
"data-turbo-confirm": t('.confirm'),
class: 'body-link',
)
else
actions << link_to(
t(".actions.lock"),
solidus_admin.lock_order_adjustments_path(@order, id: adjustment),
"data-turbo-method": :put,
"data-turbo-confirm": t('.confirm'),
class: 'body-link',
)
actions << link_to(
t(".actions.delete"),
spree.admin_order_adjustment_path(@order, adjustment),
"data-turbo-method": :delete,
"data-turbo-confirm": t('.confirm'),
class: 'body-link !text-red-500',
)
end

render component('ui/dropdown').new(
direction: :right,
class: 'relative w-fit m-auto',
).with_content(safe_join(actions))
end
},
]
end

def icon_thumbnail(name)
render component("ui/thumbnail").new(src: svg_data_uri(icon_tag(name)))
end

def svg_data_uri(data)
"data:image/svg+xml;base64,#{Base64.strict_encode64(data)}"
end

def figcaption_for_source(adjustment)
return thumbnail_caption(adjustment.label, nil) unless adjustment.source_type

# ["Spree::PromotionAction", nil, "Spree::UnitCancel", "Spree::TaxRate"]
record = adjustment.source
record_class = adjustment.source_type&.constantize
model_name = record_class.model_name.human

case record || record_class
when Spree::TaxRate
detail = link_to("#{model_name}: #{record.zone&.name || t('spree.all_zones')}", spree.edit_admin_tax_rate_path(adjustment.source_id), class: "body-link")
when Spree::PromotionAction
detail = link_to("#{model_name}: #{record.promotion.name}", spree.edit_admin_promotion_path(adjustment.source_id), class: "body-link")
else
detail = "#{model_name}: #{record.display_amount}" if record.respond_to?(:display_amount)
end

thumbnail_caption(adjustment.label, detail)
end

def figcaption_for_adjustable(adjustment)
# ["Spree::LineItem", "Spree::Order", "Spree::Shipment"]
record = adjustment.adjustable
record_class = adjustment.adjustable_type&.constantize

case record || record_class
when Spree::LineItem
variant = record.variant
options_text = variant.options_text.presence

description = options_text || variant.sku
detail = link_to(variant.product.name, solidus_admin.product_path(record.variant.product), class: "body-link")
when Spree::Order
description = "#{Spree::Order.model_name.human} ##{record.number}"
detail = record.display_total
when Spree::Shipment
description = "#{t('spree.shipment')} ##{record.number}"
detail = link_to(record.shipping_method.name, spree.edit_admin_shipping_method_path(record.shipping_method), class: "body-link")
when nil
# noop
else
name_method = [:display_name, :name, :number].find { record.respond_to? _1 } if record
price_method = [:display_amount, :display_total, :display_cost].find { record.respond_to? _1 } if record

description = record_class.model_name.human
description = "#{description} - #{record.public_send(name_method)}" if name_method

# attempt creating a link
url_options = [:admin, record, :edit, { only_path: true }]
url = begin; spree.url_for(url_options); rescue NoMethodError => e; logger.error(e.to_s); nil end

description = link_to(description, url, class: "body-link") if url
detail = record.public_send(price_method) if price_method
end

thumbnail_caption(description, detail)
end

def thumbnail_caption(first_line, second_line)
tag.figcaption(safe_join([
tag.div(first_line || NBSP, class: 'text-black body-small whitespace-nowrap text-ellipsis overflow-hidden'),
tag.div(second_line || NBSP, class: 'text-gray-500 body-small whitespace-nowrap text-ellipsis overflow-hidden')
]), class: "flex flex-col gap-0 max-w-[15rem]")
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
en:
title: "Order %{number} / Adjustments"
save: "Save"
discard: "Discard"
none: ""

actions:
title: "Actions"
delete: "Delete"
lock: "Lock"
unlock: "Unlock"
edit: "Edit"

state:
locked: "Locked"
unlocked: "Unlocked"
confirm: "Are you sure?"

totals:
adjustable: "Totals (by Adjustable)"
source: "Totals (by Source)"
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{ label: t('.taxes'), value: number_to_currency(@order.additional_tax_total) },
{ label: t('.shipping'), value: number_to_currency(@order.shipment_total) },
{ label: link_to(t('.add_promo_code'), '#', class: "body-link"), value: number_to_currency(@order.promo_total) },
{ label: link_to(t('.adjustments'), '#', class: "body-link"), value: number_to_currency(@order.adjustment_total) },
{ label: link_to(t('.adjustments'), solidus_admin.order_adjustments_path(@order), class: "body-link"), value: number_to_currency(@order.adjustment_total) },
{ label: t('.total'), value: number_to_currency(@order.total), class: 'font-semibold' }
]
) %>
Expand Down
55 changes: 55 additions & 0 deletions admin/app/controllers/solidus_admin/adjustments_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

class SolidusAdmin::AdjustmentsController < SolidusAdmin::BaseController
before_action :load_order

def index
@adjustments = @order
.all_adjustments
.eligible
.order("adjustable_type ASC, created_at ASC")
.ransack(params[:q])
.result

set_page_and_extract_portion_from(@adjustments)

respond_to do |format|
format.html do
render component('orders/show/adjustments/index').new(
order: @order,
adjustments: @adjustments,
)
end
end
end

def lock
@adjustments = @order.all_adjustments.not_finalized.where(id: params[:id])
@adjustments.each(&:finalize!)
flash[:success] = t('.success')

redirect_to order_adjustments_path(@order), status: :see_other
end

def unlock
@adjustments = @order.all_adjustments.finalized.where(id: params[:id])
@adjustments.each(&:unfinalize!)
flash[:success] = t('.success')

redirect_to order_adjustments_path(@order), status: :see_other
end

def destroy
@adjustments = @order.all_adjustments.where(id: params[:id])
@adjustments.destroy_all
flash[:success] = t('.success')

redirect_to order_adjustments_path(@order), status: :see_other
end

private

def load_order
@order = Spree::Order.find_by!(number: params[:order_id])
end
end
10 changes: 10 additions & 0 deletions admin/config/locales/adjustments.en.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
en:
solidus_admin:
adjustments:
title: "Adjustments"
lock:
success: "Locked successfully"
unlock:
success: "Unlocked successfully"
destroy:
success: "Deleted successfully"
8 changes: 8 additions & 0 deletions admin/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@
admin_resources :orders, except: [
:destroy, :index
], constraints: ->{ SolidusAdmin::Config.enable_alpha_features? } do
resources :adjustments, only: [:index] do
collection do
delete :destroy
put :lock
put :unlock
end
end

resources :line_items, only: [:destroy, :create, :update]
resource :customer
resource :ship_address, only: [:show, :edit, :update], controller: "addresses", type: "ship"
Expand Down
Loading

0 comments on commit b5e21ff

Please sign in to comment.