From b88c2b4701c85d15dd4a0e123ba9c6d236e139fd Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Mon, 22 Jun 2026 12:15:08 +0700 Subject: [PATCH] refactor: implement and utilize eloquent scopes for common model status queries across the application --- .../Commands/ApplyAttendancePenalties.php | 4 +-- .../Admin/Hr/LeaveRequestController.php | 4 +-- app/Http/Middleware/HandleInertiaRequests.php | 15 +++-------- app/Models/Cutting.php | 26 +++++++++++++++++++ app/Models/EmployeeAdvance.php | 20 ++++++++++++++ app/Models/LeaveRequest.php | 14 ++++++++++ app/Models/Order.php | 8 ++++++ .../Finance/EmployeeAdvanceService.php | 3 +-- app/Services/Hr/AttendanceService.php | 4 +-- app/Services/Hr/LeaveRequestService.php | 3 +-- .../Manage/CuttingResultPriceResolver.php | 3 +-- app/Services/Manage/CuttingService.php | 4 +-- app/Services/Manage/StockService.php | 4 +-- app/Services/System/DashboardService.php | 25 ++++++------------ 14 files changed, 90 insertions(+), 47 deletions(-) diff --git a/app/Console/Commands/ApplyAttendancePenalties.php b/app/Console/Commands/ApplyAttendancePenalties.php index 9135098..7e4753a 100644 --- a/app/Console/Commands/ApplyAttendancePenalties.php +++ b/app/Console/Commands/ApplyAttendancePenalties.php @@ -3,7 +3,6 @@ namespace App\Console\Commands; use App\Enums\EmployeeStatus; -use App\Enums\LeaveRequestStatus; use App\Enums\PayrollAdjustmentType; use App\Enums\PayrollPeriodStatus; use App\Models\Attendance; @@ -50,9 +49,8 @@ public function handle(): int $skippedDuplicate = 0; foreach ($employees as $employee) { - $hasLeave = LeaveRequest::query() + $hasLeave = LeaveRequest::approved() ->where('employee_id', $employee->id) - ->where('status', LeaveRequestStatus::APPROVED) ->whereDate('start_date', '<=', $date) ->whereDate('end_date', '>=', $date) ->exists(); diff --git a/app/Http/Controllers/Admin/Hr/LeaveRequestController.php b/app/Http/Controllers/Admin/Hr/LeaveRequestController.php index eff272a..80c04d3 100644 --- a/app/Http/Controllers/Admin/Hr/LeaveRequestController.php +++ b/app/Http/Controllers/Admin/Hr/LeaveRequestController.php @@ -2,7 +2,6 @@ namespace App\Http\Controllers\Admin\Hr; -use App\Enums\LeaveRequestStatus; use App\Enums\Permission; use App\Http\Controllers\Concerns\FlashesEntityMessage; use App\Http\Controllers\Concerns\ParsesDataTableQuery; @@ -31,9 +30,8 @@ public function index(Request $request): Response $hasPending = false; if ($user?->employee !== null) { - $hasPending = LeaveRequest::query() + $hasPending = LeaveRequest::pending() ->where('employee_id', $user->employee->id) - ->where('status', LeaveRequestStatus::PENDING) ->exists(); } diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 655432f..25a6c6c 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -2,9 +2,6 @@ namespace App\Http\Middleware; -use App\Enums\CuttingStatus; -use App\Enums\EmployeeAdvanceStatus; -use App\Enums\LeaveRequestStatus; use App\Models\Cutting; use App\Models\EmployeeAdvance; use App\Models\LeaveRequest; @@ -85,8 +82,7 @@ private function pendingLeaveRequests(Request $request): int return 0; } - return LeaveRequest::query() - ->where('status', LeaveRequestStatus::PENDING) + return LeaveRequest::pending() ->count(); } @@ -98,8 +94,7 @@ private function pendingEmployeeAdvances(Request $request): int return 0; } - return EmployeeAdvance::query() - ->where('status', EmployeeAdvanceStatus::PENDING) + return EmployeeAdvance::pending() ->count(); } @@ -111,8 +106,7 @@ private function pendingCuttings(Request $request): int return 0; } - return Cutting::query() - ->where('status', CuttingStatus::COMPLETED) + return Cutting::completed() ->count(); } @@ -124,8 +118,7 @@ private function pendingOwnerVerifications(Request $request): int return 0; } - return Cutting::query() - ->where('status', CuttingStatus::PENDING_VERIFICATION) + return Cutting::pendingVerification() ->count(); } } diff --git a/app/Models/Cutting.php b/app/Models/Cutting.php index 639a72e..20f5e90 100644 --- a/app/Models/Cutting.php +++ b/app/Models/Cutting.php @@ -7,6 +7,8 @@ use App\Models\Concerns\InteractsWithActivityLog; use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Attributes\Scope; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -72,4 +74,28 @@ public function statusLabel(): Attribute get: fn () => $this->status->label(), ); } + + #[Scope] + public function inProgress(Builder $query): void + { + $query->where('status', CuttingStatus::IN_PROGRESS); + } + + #[Scope] + public function completed(Builder $query): void + { + $query->where('status', CuttingStatus::COMPLETED); + } + + #[Scope] + public function pendingVerification(Builder $query): void + { + $query->where('status', CuttingStatus::PENDING_VERIFICATION); + } + + #[Scope] + public function verified(Builder $query): void + { + $query->where('status', CuttingStatus::VERIFIED); + } } diff --git a/app/Models/EmployeeAdvance.php b/app/Models/EmployeeAdvance.php index 25c8690..5d5809b 100644 --- a/app/Models/EmployeeAdvance.php +++ b/app/Models/EmployeeAdvance.php @@ -7,6 +7,8 @@ use App\Models\Concerns\InteractsWithActivityLog; use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Attributes\Scope; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -135,4 +137,22 @@ public function statusLabel(): Attribute get: fn () => $this->status?->label(), ); } + + #[Scope] + public function pending(Builder $query): void + { + $query->where('status', EmployeeAdvanceStatus::PENDING); + } + + #[Scope] + public function approved(Builder $query): void + { + $query->where('status', EmployeeAdvanceStatus::APPROVED); + } + + #[Scope] + public function paid(Builder $query): void + { + $query->where('status', EmployeeAdvanceStatus::PAID); + } } diff --git a/app/Models/LeaveRequest.php b/app/Models/LeaveRequest.php index 8c60959..2df9850 100644 --- a/app/Models/LeaveRequest.php +++ b/app/Models/LeaveRequest.php @@ -7,6 +7,8 @@ use App\Models\Concerns\InteractsWithActivityLog; use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Attributes\Scope; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -120,4 +122,16 @@ public function statusLabel(): Attribute get: fn () => $this->status?->label(), ); } + + #[Scope] + public function pending(Builder $query): void + { + $query->where('status', LeaveRequestStatus::PENDING); + } + + #[Scope] + public function approved(Builder $query): void + { + $query->where('status', LeaveRequestStatus::APPROVED); + } } diff --git a/app/Models/Order.php b/app/Models/Order.php index 8a42534..22a7a75 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -9,6 +9,8 @@ use App\Models\Concerns\InteractsWithActivityLog; use Illuminate\Database\Eloquent\Attributes\Appends; use Illuminate\Database\Eloquent\Attributes\Guarded; +use Illuminate\Database\Eloquent\Attributes\Scope; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -135,4 +137,10 @@ public function subtotalFormatted(): Attribute get: fn () => 'Rp '.number_format($this->subtotal, 0, ',', '.'), ); } + + #[Scope] + public function completed(Builder $query): void + { + $query->where('status', OrderStatus::COMPLETED); + } } diff --git a/app/Services/Finance/EmployeeAdvanceService.php b/app/Services/Finance/EmployeeAdvanceService.php index 5abd78f..1732a14 100644 --- a/app/Services/Finance/EmployeeAdvanceService.php +++ b/app/Services/Finance/EmployeeAdvanceService.php @@ -26,8 +26,7 @@ public function __construct( */ public function outstandingSummary(?User $user = null): array { - $query = EmployeeAdvance::query() - ->where('status', EmployeeAdvanceStatus::APPROVED) + $query = EmployeeAdvance::approved() ->when(! $user->hasAnyRole([Role::OWNER->value, Role::DEVELOPER->value, Role::DIREKTUR->value]), fn (Builder $query) => $query->where('employee_id', $user->employee?->id ?? -1)); $outstandingAmount = (int) $query->sum('amount'); diff --git a/app/Services/Hr/AttendanceService.php b/app/Services/Hr/AttendanceService.php index 9cf5757..3e3b71f 100644 --- a/app/Services/Hr/AttendanceService.php +++ b/app/Services/Hr/AttendanceService.php @@ -2,7 +2,6 @@ namespace App\Services\Hr; -use App\Enums\LeaveRequestStatus; use App\Models\Attendance; use App\Models\Employee; use App\Models\LeaveRequest; @@ -61,9 +60,8 @@ public function todayAttendanceForEmployee(Employee $employee): ?array public function isOnLeaveToday(Employee $employee): bool { - return LeaveRequest::query() + return LeaveRequest::approved() ->where('employee_id', $employee->id) - ->where('status', LeaveRequestStatus::APPROVED) ->whereDate('start_date', '<=', today()) ->whereDate('end_date', '>=', today()) ->exists(); diff --git a/app/Services/Hr/LeaveRequestService.php b/app/Services/Hr/LeaveRequestService.php index cdc5a27..9a4cab2 100644 --- a/app/Services/Hr/LeaveRequestService.php +++ b/app/Services/Hr/LeaveRequestService.php @@ -55,9 +55,8 @@ public function create(array $validated, User $user): void { $employee = $this->resolveAuthEmployee($user); - $hasPending = LeaveRequest::query() + $hasPending = LeaveRequest::pending() ->where('employee_id', $employee->id) - ->where('status', LeaveRequestStatus::PENDING) ->exists(); if ($hasPending) { diff --git a/app/Services/Manage/CuttingResultPriceResolver.php b/app/Services/Manage/CuttingResultPriceResolver.php index 03e4443..a522b07 100644 --- a/app/Services/Manage/CuttingResultPriceResolver.php +++ b/app/Services/Manage/CuttingResultPriceResolver.php @@ -2,7 +2,6 @@ namespace App\Services\Manage; -use App\Enums\CuttingStatus; use App\Enums\PriceType; use App\Models\CuttingResultPrice; @@ -13,7 +12,7 @@ public function resolve(int $productVariantId, PriceType $priceType): ?CuttingRe return CuttingResultPrice::query() ->where('product_variant_id', $productVariantId) ->where('price_type', $priceType) - ->whereHas('cutting', fn ($query) => $query->where('status', CuttingStatus::VERIFIED)) + ->whereHas('cutting', fn ($query) => $query->verified()) ->join('cuttings', 'cutting_result_prices.cutting_id', '=', 'cuttings.id') ->orderByDesc('cuttings.created_at') ->select('cutting_result_prices.*') diff --git a/app/Services/Manage/CuttingService.php b/app/Services/Manage/CuttingService.php index c2d3d03..0170061 100644 --- a/app/Services/Manage/CuttingService.php +++ b/app/Services/Manage/CuttingService.php @@ -87,7 +87,7 @@ public function getInProgressCuttings(User $user): Collection 'results.productVariant.product:id,name', 'results.productVariant:id,product_id,name', ]) - ->where('status', CuttingStatus::IN_PROGRESS) + ->inProgress() ->latest() ->get() ->each(function (Cutting $cutting) use ($user): void { @@ -115,7 +115,7 @@ public function getCompletedCuttings(User $user): Collection 'results.productVariant.product:id,name', 'results.productVariant:id,product_id,name', ]) - ->where('status', CuttingStatus::COMPLETED) + ->completed() ->latest() ->get() ->each(function (Cutting $cutting) use ($user): void { diff --git a/app/Services/Manage/StockService.php b/app/Services/Manage/StockService.php index d670cfa..78271c8 100644 --- a/app/Services/Manage/StockService.php +++ b/app/Services/Manage/StockService.php @@ -34,7 +34,7 @@ public function getPendingVerificationCuttings(User $user): Collection 'results.productVariant.product:id,name', 'results.productVariant:id,product_id,name', ]) - ->where('status', CuttingStatus::COMPLETED) + ->completed() ->latest() ->get() ->each(function (Cutting $cutting): void { @@ -58,7 +58,7 @@ public function getPendingApprovalCuttings(User $user): Collection 'results.productVariant:id,product_id,name', 'resultPrices.productVariant:id,product_id,name', ]) - ->where('status', CuttingStatus::PENDING_VERIFICATION) + ->pendingVerification() ->latest() ->get() ->each(function (Cutting $cutting): void { diff --git a/app/Services/System/DashboardService.php b/app/Services/System/DashboardService.php index caed90b..d19e945 100644 --- a/app/Services/System/DashboardService.php +++ b/app/Services/System/DashboardService.php @@ -3,7 +3,6 @@ namespace App\Services\System; use App\Enums\CuttingStatus; -use App\Enums\EmployeeAdvanceStatus; use App\Enums\EmploymentStatus; use App\Enums\OrderChannel; use App\Enums\OrderStatus; @@ -134,8 +133,7 @@ public function getTopSuppliers(): array public function getTopCustomers(): array { - return Order::query() - ->where('status', OrderStatus::COMPLETED) + return Order::completed() ->join('customers', 'orders.customer_id', '=', 'customers.id') ->selectRaw('customers.name, SUM(orders.total_amount) as total_amount, COUNT(orders.id) as order_count') ->groupBy('customers.id', 'customers.name') @@ -274,13 +272,11 @@ public function getOrderStats(): array public function getRevenueSummary(): array { - $data = Order::query() - ->where('status', OrderStatus::COMPLETED) + $data = Order::completed() ->selectRaw('SUM(total_amount) as total_revenue, SUM(discount) as total_discount, SUM(shipping_cost) as total_shipping, COUNT(*) as total_orders, AVG(total_amount) as avg_order') ->first(); - $totalMarketplaceFees = Order::query() - ->where('status', OrderStatus::COMPLETED) + $totalMarketplaceFees = Order::completed() ->whereNotNull('marketplace_settings_snapshot') ->get() ->sum(fn ($order) => (int) ($order->marketplace_settings_snapshot['total_fee_amount'] ?? 0)); @@ -298,8 +294,7 @@ public function getRevenueSummary(): array public function getMarketplaceSummary(): array { - $marketplaceOrders = Order::query() - ->where('status', OrderStatus::COMPLETED) + $marketplaceOrders = Order::completed() ->whereIn('channel', [OrderChannel::SHOPEE, OrderChannel::TIKTOK]) ->whereNotNull('marketplace_settings_snapshot') ->get(); @@ -378,18 +373,15 @@ public function getMonthlyExpenses(Carbon $startOfMonth, Carbon $endOfMonth): ar public function getKasbonSummary(): array { - $pending = EmployeeAdvance::query() - ->where('status', EmployeeAdvanceStatus::PENDING) + $pending = EmployeeAdvance::pending() ->selectRaw('COUNT(*) as count, COALESCE(SUM(amount), 0) as total') ->first(); - $approved = EmployeeAdvance::query() - ->where('status', EmployeeAdvanceStatus::APPROVED) + $approved = EmployeeAdvance::approved() ->selectRaw('COUNT(*) as count, COALESCE(SUM(amount), 0) as total') ->first(); - $paid = EmployeeAdvance::query() - ->where('status', EmployeeAdvanceStatus::PAID) + $paid = EmployeeAdvance::paid() ->selectRaw('COUNT(*) as count, COALESCE(SUM(amount), 0) as total') ->first(); @@ -530,8 +522,7 @@ public function getMonthlyRevenueTrend(): array $start = Carbon::create($month['year'], $month['month'], 1)->startOfMonth(); $end = $start->copy()->endOfMonth(); - $data = Order::query() - ->where('status', OrderStatus::COMPLETED) + $data = Order::completed() ->whereBetween('created_at', [$start, $end]) ->selectRaw('COALESCE(SUM(total_amount), 0) as total, COUNT(*) as count') ->first();