OwnerVerificationAction::class, 'payload' => 'array', 'status' => OwnerVerificationStatus::class, 'verified_at' => 'datetime', ]; } // 3. Scope (grouped by column, then alphabetical) // Column Group: status #[Scope] protected function approved(Builder $query): void { $query->where('status', OwnerVerificationStatus::APPROVED); } #[Scope] protected function pending(Builder $query): void { $query->where('status', OwnerVerificationStatus::PENDING); } #[Scope] protected function rejected(Builder $query): void { $query->where('status', OwnerVerificationStatus::REJECTED); } // Scope lainnya #[Scope] protected function forSubmitter(Builder $query, User $user): void { $query->where('submitted_by_id', $user->id); } #[Scope] protected function visibleTo(Builder $query, User $user): void { if ($user->can(Permission::OWNER_VERIFICATIONS_VERIFY->value)) { return; } $query->forSubmitter($user); } // 4. Attribute public function actionLabel(): Attribute { return Attribute::make( get: fn () => $this->action?->label(), ); } public function createdAtFormatted(): Attribute { return Attribute::make( get: fn () => $this->created_at?->translatedFormat('l, d F Y H:i'), ); } public function isPending(): Attribute { return Attribute::make( get: fn () => $this->status === OwnerVerificationStatus::PENDING, ); } public function statusLabel(): Attribute { return Attribute::make( get: fn () => $this->status?->label(), ); } public function subjectLabel(): Attribute { return Attribute::make( get: fn () => ModelLabel::for($this->subject_type), ); } public function submittedByName(): Attribute { return Attribute::make( get: fn () => $this->submittedBy?->profile?->full_name ?? $this->submittedBy?->username ?? '-', ); } public function verifiedAtFormatted(): Attribute { return Attribute::make( get: fn () => $this->verified_at?->translatedFormat('l, d F Y H:i'), ); } public function verifiedByName(): Attribute { return Attribute::make( get: fn () => $this->verifiedBy?->profile?->full_name ?? $this->verifiedBy?->username, ); } // 5. Other Methods public static function mediaModuleName(): string { return 'owner_verification_request'; } public function pendingToggleStatus(): ?string { if ($this->action !== OwnerVerificationAction::TOGGLE_STATUS) { return null; } $payload = is_array($this->payload) ? $this->payload : []; $new = $payload['new'] ?? null; if (! is_array($new) || ! array_key_exists('status', $new)) { return null; } return $new['status']; } public function priceImageCollection(int $index): string { return "price_images_{$index}"; } public function variantImageCollection(int $index): string { return "variant_images_{$index}"; } // 6. Relation public function subject(): MorphTo { return $this->morphTo(); } public function submittedBy(): BelongsTo { return $this->belongsTo(User::class, 'submitted_by_id')->withTrashed(); } public function verifiedBy(): BelongsTo { return $this->belongsTo(User::class, 'verified_by_id')->withTrashed(); } }