Feat: Updating Product Indexer, and Product Sort

This commit is contained in:
2026-09-23 09:41:21 +03:00
parent 4e15d8ef8c
commit 4c0974bf84
2 changed files with 27 additions and 0 deletions
+7
View File
@@ -14,6 +14,7 @@ enum ProductSort: string
case PriceAsc = 'price_asc'; case PriceAsc = 'price_asc';
case PriceDesc = 'price_desc'; case PriceDesc = 'price_desc';
case Newest = 'newest'; case Newest = 'newest';
case Popularity = 'popularity';
public function toMeilisearchSort(): string public function toMeilisearchSort(): string
{ {
@@ -21,6 +22,12 @@ enum ProductSort: string
self::PriceAsc => 'price:asc', self::PriceAsc => 'price:asc',
self::PriceDesc => 'price:desc', self::PriceDesc => 'price:desc',
self::Newest => 'created_at:desc', self::Newest => 'created_at:desc',
// order_count — see Modules\Core\Catalog\Services\
// ProductIndexer::toSearchableArray()'s own docblock: the same
// trailing-year, physical-order-line-count definition Lunar's
// own admin dashboard "Popular Products" widget already uses,
// aggregated per product rather than per variant.
self::Popularity => 'order_count:desc',
}; };
} }
} }
+20
View File
@@ -5,6 +5,7 @@ namespace Modules\Core\Catalog\Services;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Lunar\Models\Currency; use Lunar\Models\Currency;
use Lunar\Models\OrderLine;
use Lunar\Models\Price; use Lunar\Models\Price;
use Lunar\Models\Product; use Lunar\Models\Product;
use Lunar\Models\ProductVariant; use Lunar\Models\ProductVariant;
@@ -103,6 +104,7 @@ class ProductIndexer extends BaseProductIndexer
return [ return [
...parent::getSortableFields(), ...parent::getSortableFields(),
'price', 'price',
'order_count',
]; ];
} }
@@ -161,6 +163,24 @@ class ProductIndexer extends BaseProductIndexer
$data['in_stock'] = $model->variants->contains( $data['in_stock'] = $model->variants->contains(
fn (ProductVariant $variant) => $variant->canBeFulfilledAtQuantity(1) fn (ProductVariant $variant) => $variant->canBeFulfilledAtQuantity(1)
); );
// Same "popular" definition as Lunar's own admin dashboard widget
// (Lunar\Admin\Filament\Widgets\Dashboard\Orders\
// PopularProductsTable) — order-line COUNT, not summed quantity,
// over the trailing year, physical lines only — just aggregated
// per PRODUCT here (across all its variants) rather than per
// variant/identifier, since a storefront "sort by popularity"
// ranks products, not individual variant SKUs. Necessarily as
// stale as any other reindex-time field here (in_stock, price) —
// there's no live equivalent without a query per page load.
$data['order_count'] = OrderLine::query()
->whereIn('purchasable_id', $model->variants->pluck('id'))
->where('purchasable_type', 'product_variant')
->where('type', 'physical')
->whereHas('order', fn ($query) => $query->whereBetween('placed_at', [
now()->subYear()->startOfDay(),
now()->endOfDay(),
]))
->count();
$data['recommendations'] = app(RecommendationService::class) $data['recommendations'] = app(RecommendationService::class)
->recommend($model) ->recommend($model)
->load(['media', 'variants.prices']) ->load(['media', 'variants.prices'])