refactor: streamline variant and price loading in product-related services
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (8.3) (push) Waiting to run
tests / ci (8.4) (push) Waiting to run
tests / ci (8.5) (push) Waiting to run

- Removed unnecessary ordering by 'created_at' in variant loading across multiple services and models.
- Implemented global scopes for ordering product variants and raw material prices by 'name' and 'variant', respectively.
- Enhanced code readability and maintainability by simplifying query structures in ProductController, OrderService, and others.
This commit is contained in:
Yoga Pangestu 2026-07-29 15:06:16 +07:00
parent 9cbf841feb
commit 9089b32d7b
9 changed files with 23 additions and 14 deletions

View File

@ -122,8 +122,7 @@ public function show(Product $product): JsonResponse
$product->load([ $product->load([
'categories', 'categories',
'variants' => fn ($query) => $query 'variants' => fn ($query) => $query
->with(['media', 'prices']) ->with(['media', 'prices']),
->orderBy('created_at'),
]); ]);
$product->variants->each(function ($variant): void { $product->variants->each(function ($variant): void {

View File

@ -97,8 +97,7 @@ public static function getActiveWithVariantsAndCategories(): Collection
->with([ ->with([
'categories', 'categories',
'variants' => fn ($query) => $query 'variants' => fn ($query) => $query
->with('media') ->with('media'),
->orderBy('created_at'),
]) ])
->get(); ->get();
} }
@ -123,6 +122,6 @@ public function pendingOwnerVerificationRequest(): MorphOne
public function variants(): HasMany public function variants(): HasMany
{ {
return $this->hasMany(ProductVariant::class); return $this->hasMany(ProductVariant::class)->orderBy('name');
} }
} }

View File

@ -6,6 +6,7 @@
use App\Models\Concerns\InteractsWithActivityLog; use App\Models\Concerns\InteractsWithActivityLog;
use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Appends;
use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Guarded;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@ -24,6 +25,13 @@ class ProductVariant extends Model implements HasMedia
private const MIN_STOCK = 5; private const MIN_STOCK = 5;
protected static function booted(): void
{
static::addGlobalScope('ordered', function (Builder $query): void {
$query->orderBy('name');
});
}
// 2. Casting // 2. Casting
protected function casts(): array protected function casts(): array
{ {

View File

@ -107,6 +107,6 @@ public function pendingOwnerVerificationRequest(): MorphOne
public function prices(): HasMany public function prices(): HasMany
{ {
return $this->hasMany(RawMaterialPrice::class); return $this->hasMany(RawMaterialPrice::class)->orderBy('variant');
} }
} }

View File

@ -6,6 +6,7 @@
use App\Models\Concerns\InteractsWithActivityLog; use App\Models\Concerns\InteractsWithActivityLog;
use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Appends;
use Illuminate\Database\Eloquent\Attributes\Guarded; use Illuminate\Database\Eloquent\Attributes\Guarded;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@ -22,6 +23,13 @@ class RawMaterialPrice extends Model implements HasMedia
// 1. Use Trait // 1. Use Trait
use HasFactory, HasModuleMedia, InteractsWithActivityLog, SoftDeletes; use HasFactory, HasModuleMedia, InteractsWithActivityLog, SoftDeletes;
protected static function booted(): void
{
static::addGlobalScope('ordered', function (Builder $query): void {
$query->orderBy('variant');
});
}
// 2. Casting // 2. Casting
protected function casts(): array protected function casts(): array
{ {

View File

@ -162,7 +162,6 @@ public function catalogItems(?Order $order = null, ?User $user = null): Collecti
->with([ ->with([
'variants' => fn ($query) => $query 'variants' => fn ($query) => $query
->with('media') ->with('media')
->orderBy('created_at')
->where(fn ($q) => $q ->where(fn ($q) => $q
->where('stock', '>', 0) ->where('stock', '>', 0)
->orWhere('reject_stock', '>', 0) ->orWhere('reject_stock', '>', 0)

View File

@ -94,8 +94,7 @@ public function productCatalog(?Restock $restock = null, ?User $user = null): Co
return Product::query() return Product::query()
->with([ ->with([
'variants' => fn ($query) => $query 'variants' => fn ($query) => $query
->with(['media', 'prices']) ->with(['media', 'prices']),
->orderBy('created_at'),
]) ])
->where(function (Builder $query) use ($selectedVariantIds): void { ->where(function (Builder $query) use ($selectedVariantIds): void {
$query->active(); $query->active();

View File

@ -59,8 +59,7 @@ public function catalogItems(): array
->active() ->active()
->with([ ->with([
'variants' => fn ($query) => $query 'variants' => fn ($query) => $query
->select('id', 'product_id', 'name', 'stock', 'retail_stock', 'reject_stock') ->select('id', 'product_id', 'name', 'stock', 'retail_stock', 'reject_stock'),
->orderBy('created_at'),
]) ])
->orderBy('name') ->orderBy('name')
->get() ->get()

View File

@ -41,7 +41,6 @@ public function paginateForIndex(array $tableQuery, string $status, string $cate
'pendingOwnerVerificationRequest.submittedBy.profile', 'pendingOwnerVerificationRequest.submittedBy.profile',
'variants' => fn ($query) => $query 'variants' => fn ($query) => $query
->with(['media', 'prices' => fn ($query) => $query->orderBy('type')]) ->with(['media', 'prices' => fn ($query) => $query->orderBy('type')])
->orderBy('created_at')
->when($tableQuery['search'] !== '', function ($query) use ($tableQuery): void { ->when($tableQuery['search'] !== '', function ($query) use ($tableQuery): void {
$query->where('name', 'like', "%{$tableQuery['search']}%"); $query->where('name', 'like', "%{$tableQuery['search']}%");
}), }),
@ -113,8 +112,7 @@ public function findForEdit(Product $product): Product
$product->load([ $product->load([
'categories', 'categories',
'variants' => fn ($query) => $query 'variants' => fn ($query) => $query
->with(['media', 'prices']) ->with(['media', 'prices']),
->orderBy('created_at'),
]); ]);
$product->variants->each(function (ProductVariant $variant): void { $product->variants->each(function (ProductVariant $variant): void {