refactor: implement local scopes for enums with #[Scope] attribute across models

- Added local scopes for Enum-based fields (status, type, decision) in models: Cooperation, VerificationRequest, PartnerMedia, CooperationProposal, CooperationMedia, and VerificationReview.
- Refactored query logic in Commands, Services, and Filament Resources to use the new scopes for better readability and maintainability.
- Added specific pivot status scopes in PartnerMedia model for cleaner relationship filtering.
- Fixed incorrect Enum usage in ViewCooperation.php during the refactoring process.
- Standardized code style for closures and string concatenation in the modified files.
This commit is contained in:
Yoga Pangestu 2026-01-12 11:14:22 +07:00
parent 0b15d95395
commit 9ca4e68de9
12 changed files with 177 additions and 27 deletions

View File

@ -33,10 +33,10 @@ public function handle()
$today = Carbon::today();
Log::info('Running UpdateCooperationStatusJob at ' . now());
Log::info('Running UpdateCooperationStatusJob at '.now());
// 1. PENDING -> ASSIGNMENT (final_submission_date)
$updatedPending = Cooperation::where('status', CooperationStatus::PENDING)
$updatedPending = Cooperation::pending()
->whereDate('final_submission_date', '<=', $today)
->update(['status' => CooperationStatus::ASSIGNMENT]);
@ -45,7 +45,7 @@ public function handle()
}
// 2. ASSIGNMENT -> VERIFICATION (assignment_deadline)
$updatedAssignment = Cooperation::where('status', CooperationStatus::ASSIGNMENT)
$updatedAssignment = Cooperation::assignment()
->whereDate('assignment_deadline', '<=', $today)
->update(['status' => CooperationStatus::VERIFICATION]);
@ -54,7 +54,7 @@ public function handle()
}
// 3. VERIFICATION -> PAYMENT (verification_deadline)
$updatedVerification = Cooperation::where('status', CooperationStatus::VERIFICATION)
$updatedVerification = Cooperation::verification()
->whereDate('verification_deadline', '<=', $today)
->update(['status' => CooperationStatus::PAYMENT]);

View File

@ -80,10 +80,10 @@ public function getStatusCounts(): array
{
return [
'all' => VerificationRequest::count(),
'pending' => VerificationRequest::where('status', VerificationStatus::PENDING)->count(),
'revision' => VerificationRequest::where('status', VerificationStatus::NEED_REVISION)->count(),
'approved' => VerificationRequest::where('status', VerificationStatus::APPROVED)->count(),
'rejected' => VerificationRequest::where('status', VerificationStatus::REJECTED)->count(),
'pending' => VerificationRequest::pending()->count(),
'revision' => VerificationRequest::needRevision()->count(),
'approved' => VerificationRequest::approved()->count(),
'rejected' => VerificationRequest::rejected()->count(),
];
}

View File

@ -2,7 +2,7 @@
namespace App\Filament\Resources\Manage\Cooperations\Pages;
use App\Enums\CooperationStatus;
use App\Enums\ApprovalStatus;
use App\Filament\Resources\Manage\Cooperations\CooperationResource;
use Filament\Actions\Action;
use Filament\Notifications\Notification;
@ -116,11 +116,11 @@ protected function getMediaResponseStatus($record): string
{
$mediaStatuses = $record->cooperationMedia->pluck('status')->unique();
if ($mediaStatuses->contains(CooperationStatus::ACCEPTED)) {
if ($mediaStatuses->contains(ApprovalStatus::ACCEPTED)) {
return 'completed';
}
if ($mediaStatuses->contains(CooperationStatus::REJECTED)) {
if ($mediaStatuses->contains(ApprovalStatus::REJECTED)) {
return 'rejected';
}
@ -139,7 +139,7 @@ protected function getMediaResponseDate($record)
protected function getProposalStatus($record): string
{
if ($record->proposals->isNotEmpty()) {
if ($record->proposals()->exists()) {
return 'completed';
}
@ -157,11 +157,11 @@ protected function getProposalReviewStatus($record): string
{
$proposals = $record->proposals;
if ($proposals->where('status', CooperationStatus::ACCEPTED)->isNotEmpty()) {
if ($record->proposals()->accepted()->exists()) {
return 'completed';
}
if ($proposals->where('status', CooperationStatus::REJECTED)->isNotEmpty()) {
if ($record->proposals()->rejected()->exists()) {
return 'rejected';
}
@ -268,13 +268,13 @@ protected function getHeaderActions(): array
})
->first();
if ($cooperationMedia && $cooperationMedia->status === CooperationStatus::PENDING) {
if ($cooperationMedia && $cooperationMedia->status === ApprovalStatus::PENDING) {
$actions[] = Action::make('accept')
->label('Terima Kerja Sama')
->icon('heroicon-o-check-circle')
->color('success')
->action(function () use ($cooperationMedia) {
$cooperationMedia->update(['status' => CooperationStatus::ACCEPTED]);
$cooperationMedia->update(['status' => ApprovalStatus::ACCEPTED]);
Notification::make()
->title('Kerja Sama Diterima')
->success()
@ -286,7 +286,7 @@ protected function getHeaderActions(): array
->icon('heroicon-o-x-circle')
->color('danger')
->action(function () use ($cooperationMedia) {
$cooperationMedia->update(['status' => CooperationStatus::REJECTED]);
$cooperationMedia->update(['status' => ApprovalStatus::REJECTED]);
Notification::make()
->title('Kerja Sama Ditolak')
->success()

View File

@ -121,6 +121,6 @@ protected function canCreateTaskAssignment(): bool
$cooperation = $this->getOwnerRecord();
// Can create task assignment only if there are accepted proposals
return $cooperation->proposals()->where('status', ApprovalStatus::ACCEPTED)->exists();
return $cooperation->proposals()->accepted()->exists();
}
}

View File

@ -91,9 +91,9 @@ public static function configure(Table $table): Table
->html()
->getStateUsing(function (Cooperation $record) {
$record->loadCount([
'partnerMedia as approved_count' => fn ($query) => $query->where('cooperation_media.status', ApprovalStatus::ACCEPTED),
'partnerMedia as rejected_count' => fn ($query) => $query->where('cooperation_media.status', ApprovalStatus::REJECTED),
'partnerMedia as pending_count' => fn ($query) => $query->where('cooperation_media.status', ApprovalStatus::PENDING),
'partnerMedia as approved_count' => fn ($query) => $query->wherePivotAccepted(),
'partnerMedia as rejected_count' => fn ($query) => $query->wherePivotRejected(),
'partnerMedia as pending_count' => fn ($query) => $query->wherePivotPending(),
]);
$totalCount = $record->partnerMedia()->count();
@ -314,10 +314,7 @@ public static function configure(Table $table): Table
&& $cooperationMedia->status === ApprovalStatus::ACCEPTED
&& ! $record->proposals()
->where('partner_media_id', $cooperationMedia->partner_media_id)
->whereIn('status', [
ApprovalStatus::ACCEPTED,
ApprovalStatus::PENDING,
])
->where(fn ($q) => $q->accepted()->orWhere(fn ($q) => $q->pending()))
->exists();
})
->modalWidth(Width::Large),

View File

@ -3,6 +3,8 @@
namespace App\Models;
use App\Enums\CooperationStatus;
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
@ -31,6 +33,36 @@ protected function casts(): array
];
}
#[Scope]
protected function pending(Builder $query): void
{
$query->where('status', CooperationStatus::PENDING);
}
#[Scope]
protected function assignment(Builder $query): void
{
$query->where('status', CooperationStatus::ASSIGNMENT);
}
#[Scope]
protected function verification(Builder $query): void
{
$query->where('status', CooperationStatus::VERIFICATION);
}
#[Scope]
protected function payment(Builder $query): void
{
$query->where('status', CooperationStatus::PAYMENT);
}
#[Scope]
protected function completed(Builder $query): void
{
$query->where('status', CooperationStatus::COMPLETED);
}
public function proposals(): HasMany
{
return $this->hasMany(CooperationProposal::class);

View File

@ -3,6 +3,8 @@
namespace App\Models;
use App\Enums\ApprovalStatus;
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
@ -23,6 +25,24 @@ protected function casts(): array
];
}
#[Scope]
protected function pending(Builder $query): void
{
$query->where('status', ApprovalStatus::PENDING);
}
#[Scope]
protected function accepted(Builder $query): void
{
$query->where('status', ApprovalStatus::ACCEPTED);
}
#[Scope]
protected function rejected(Builder $query): void
{
$query->where('status', ApprovalStatus::REJECTED);
}
public function cooperation(): BelongsTo
{
return $this->belongsTo(Cooperation::class);

View File

@ -3,6 +3,8 @@
namespace App\Models;
use App\Enums\ApprovalStatus;
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@ -25,6 +27,24 @@ protected function casts(): array
];
}
#[Scope]
protected function pending(Builder $query): void
{
$query->where('status', ApprovalStatus::PENDING);
}
#[Scope]
protected function accepted(Builder $query): void
{
$query->where('status', ApprovalStatus::ACCEPTED);
}
#[Scope]
protected function rejected(Builder $query): void
{
$query->where('status', ApprovalStatus::REJECTED);
}
public function cooperation(): BelongsTo
{
return $this->belongsTo(Cooperation::class);

View File

@ -2,6 +2,7 @@
namespace App\Models;
use App\Enums\ApprovalStatus;
use App\Enums\MediaClassification;
use App\Enums\MediaType;
use App\Enums\VerificationStatus;
@ -31,14 +32,56 @@ protected function casts(): array
];
}
#[Scope]
protected function pending(Builder $query): void
{
$query->where('status', VerificationStatus::PENDING);
}
#[Scope]
protected function approved(Builder $query): void
{
$query->where('status', VerificationStatus::APPROVED);
}
#[Scope]
protected function needRevision(Builder $query): void
{
$query->where('status', VerificationStatus::NEED_REVISION);
}
#[Scope]
protected function rejected(Builder $query): void
{
$query->where('status', VerificationStatus::REJECTED);
}
#[Scope]
protected function verified(Builder $query): void
{
$query->whereHas('company.verificationRequest', function ($q) {
$q->where('status', VerificationStatus::APPROVED);
$q->approved();
});
}
#[Scope]
protected function wherePivotAccepted(Builder $query): void
{
$query->where('cooperation_media.status', ApprovalStatus::ACCEPTED);
}
#[Scope]
protected function wherePivotRejected(Builder $query): void
{
$query->where('cooperation_media.status', ApprovalStatus::REJECTED);
}
#[Scope]
protected function wherePivotPending(Builder $query): void
{
$query->where('cooperation_media.status', ApprovalStatus::PENDING);
}
public function company(): BelongsTo
{
return $this->belongsTo(Company::class);

View File

@ -29,6 +29,24 @@ protected function pending(Builder $query): void
$query->where('status', VerificationStatus::PENDING);
}
#[Scope]
protected function approved(Builder $query): void
{
$query->where('status', VerificationStatus::APPROVED);
}
#[Scope]
protected function needRevision(Builder $query): void
{
$query->where('status', VerificationStatus::NEED_REVISION);
}
#[Scope]
protected function rejected(Builder $query): void
{
$query->where('status', VerificationStatus::REJECTED);
}
public function company(): BelongsTo
{
return $this->belongsTo(Company::class);

View File

@ -3,6 +3,8 @@
namespace App\Models;
use App\Enums\DecisionAdmin;
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
@ -20,6 +22,24 @@ protected function casts(): array
];
}
#[Scope]
protected function approved(Builder $query): void
{
$query->where('decision', DecisionAdmin::APPROVED);
}
#[Scope]
protected function needRevision(Builder $query): void
{
$query->where('decision', DecisionAdmin::NEED_REVISION);
}
#[Scope]
protected function rejected(Builder $query): void
{
$query->where('decision', DecisionAdmin::REJECTED);
}
public function verificationRequest(): BelongsTo
{
return $this->belongsTo(VerificationRequest::class);

View File

@ -101,7 +101,7 @@ public function getLatestReviewNotes(?VerificationRequest $verificationRequest):
}
$latestReview = $verificationRequest->reviews()
->whereIn('decision', [DecisionAdmin::NEED_REVISION, DecisionAdmin::REJECTED])
->where(fn ($q) => $q->needRevision()->orWhere(fn ($q) => $q->rejected()))
->latest()
->first();