diff --git a/app/controllers/admin/products_v3_controller.rb b/app/controllers/admin/products_v3_controller.rb index 6d1ae388cb..468e27e733 100644 --- a/app/controllers/admin/products_v3_controller.rb +++ b/app/controllers/admin/products_v3_controller.rb @@ -124,11 +124,21 @@ module Admin @per_page = params[:per_page].presence || 15 @q = params.permit(q: {})[:q] || { s: 'name asc' } - # Transform on_hand sorting to include backorderable_priority (on-demand) for proper ordering + # Transform on_hand sorting to properly handle On-Demand products: + # - On-Demand products should ignore on_hand completely and sort alphabetically. + # - Non-On-Demand products should continue sorting by on_hand as usual. if @q[:s] == 'on_hand asc' - @q[:s] = ['backorderable_priority asc', @q[:s]] + @q[:s] = [ + 'backorderable_priority asc', + 'backorderable_name asc', + @q[:s] + ] elsif @q[:s] == 'on_hand desc' - @q[:s] = ['backorderable_priority desc', @q[:s]] + @q[:s] = [ + 'backorderable_priority desc', + 'backorderable_name asc', + @q[:s] + ] end end @@ -173,6 +183,7 @@ module Admin product_query = product_query.select( Arel.sql('spree_products.*'), Spree::Product.backorderable_priority_sql, + Spree::Product.backorderable_name_sql, Spree::Product.on_hand_sql ) end diff --git a/app/models/concerns/product_sort_by_stocks.rb b/app/models/concerns/product_sort_by_stocks.rb index 1fce5fda3f..763327fb42 100644 --- a/app/models/concerns/product_sort_by_stocks.rb +++ b/app/models/concerns/product_sort_by_stocks.rb @@ -3,7 +3,7 @@ module ProductSortByStocks extend ActiveSupport::Concern - included do + included do # rubocop:disable Metrics/BlockLength @on_hand_sql = Arel.sql("( SELECT COALESCE(SUM(si.count_on_hand), 0) FROM spree_variants v @@ -20,8 +20,18 @@ module ProductSortByStocks GROUP BY v.product_id )") + # When a product is On-Demand (backorderable = true), return the product name. + # This allows alphabetical ordering inside the On-Demand group. + # For non-On-Demand products, return NULL so normal on_hand sorting still applies. + @backorderable_name_sql = Arel.sql(" + CASE + WHEN (#{@backorderable_priority_sql}) THEN spree_products.name + ELSE NULL + END + ") + class << self - attr_reader :on_hand_sql, :backorderable_priority_sql + attr_reader :on_hand_sql, :backorderable_priority_sql, :backorderable_name_sql end ransacker :on_hand do @@ -31,5 +41,9 @@ module ProductSortByStocks ransacker :backorderable_priority do @backorderable_priority_sql end + + ransacker :backorderable_name do + @backorderable_name_sql + end end end diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index 5b2c4d2838..2ad3561b6c 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -31,7 +31,8 @@ module Spree acts_as_paranoid - searchable_attributes :meta_keywords, :sku, :on_hand, :backorderable_priority + searchable_attributes :meta_keywords, :sku, :on_hand, :backorderable_priority, + :backorderable_name searchable_associations :properties, :variants searchable_scopes :active, :with_properties