refactor: move verification logic from VerificationService to the Verification Filament page.
This commit is contained in:
parent
9005f9cbec
commit
f06d8d100c
@ -8,8 +8,8 @@
|
|||||||
use App\Filament\Support\CheerfulNotification;
|
use App\Filament\Support\CheerfulNotification;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\VerificationRequest;
|
use App\Models\VerificationRequest;
|
||||||
|
use App\Models\VerificationReview;
|
||||||
use App\Notifications\BroadcastNotification;
|
use App\Notifications\BroadcastNotification;
|
||||||
use App\Services\VerificationService;
|
|
||||||
use BackedEnum;
|
use BackedEnum;
|
||||||
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
|
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
|
||||||
use Filament\Actions\Action;
|
use Filament\Actions\Action;
|
||||||
@ -21,6 +21,7 @@
|
|||||||
use Filament\Pages\Page;
|
use Filament\Pages\Page;
|
||||||
use Filament\Support\Enums\Width;
|
use Filament\Support\Enums\Width;
|
||||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use UnitEnum;
|
use UnitEnum;
|
||||||
|
|
||||||
@ -42,15 +43,8 @@ class AdminVerification extends Page implements HasActions, HasForms
|
|||||||
|
|
||||||
protected static ?string $title = 'Verifikasi Rekanan';
|
protected static ?string $title = 'Verifikasi Rekanan';
|
||||||
|
|
||||||
protected VerificationService $verificationService;
|
|
||||||
|
|
||||||
protected string $view = 'filament.pages.admin-verification';
|
protected string $view = 'filament.pages.admin-verification';
|
||||||
|
|
||||||
public function boot(): void
|
|
||||||
{
|
|
||||||
$this->verificationService = app(VerificationService::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getNavigationBadge(): ?string
|
public static function getNavigationBadge(): ?string
|
||||||
{
|
{
|
||||||
return VerificationRequest::query()->pending()->count();
|
return VerificationRequest::query()->pending()->count();
|
||||||
@ -96,7 +90,7 @@ public function getStatusCounts(): array
|
|||||||
*/
|
*/
|
||||||
public function getCompanyName(VerificationRequest $request): string
|
public function getCompanyName(VerificationRequest $request): string
|
||||||
{
|
{
|
||||||
return $this->verificationService->getCompanyName($request);
|
return $request->company?->name ?? 'Data tidak ditemukan';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,7 +110,27 @@ public function getDetailUrl(VerificationRequest $request): ?string
|
|||||||
*/
|
*/
|
||||||
public function getVerificationSummary(VerificationRequest $request): array
|
public function getVerificationSummary(VerificationRequest $request): array
|
||||||
{
|
{
|
||||||
return $this->verificationService->getVerificationSummary($request);
|
$company = $request->company;
|
||||||
|
$media = $company?->partnerMedia;
|
||||||
|
$journalists = $media?->journalists ?? collect();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'company' => [
|
||||||
|
'name' => $company?->name ?? 'Belum diisi',
|
||||||
|
'email' => $company?->email ?? '-',
|
||||||
|
'exists' => $company !== null,
|
||||||
|
],
|
||||||
|
'media' => [
|
||||||
|
'name' => $media?->name ?? 'Belum diisi',
|
||||||
|
'type' => $media?->type?->getLabel() ?? '-',
|
||||||
|
'exists' => $media !== null,
|
||||||
|
],
|
||||||
|
'journalists' => [
|
||||||
|
'count' => $journalists->count(),
|
||||||
|
'names' => $journalists->pluck('name')->take(3)->toArray(),
|
||||||
|
'exists' => $journalists->count() > 0,
|
||||||
|
],
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -242,7 +256,28 @@ protected function processReview(int $requestId, DecisionAdmin $decision, ?strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->verificationService->processReview($verificationRequest, $decision, $note);
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
// Create review record
|
||||||
|
VerificationReview::create([
|
||||||
|
'verification_request_id' => $verificationRequest->id,
|
||||||
|
'reviewer_id' => auth()->id(),
|
||||||
|
'decision' => $decision,
|
||||||
|
'note' => $note,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Update verification request status
|
||||||
|
$newStatus = match ($decision) {
|
||||||
|
DecisionAdmin::APPROVED => VerificationStatus::APPROVED,
|
||||||
|
DecisionAdmin::NEED_REVISION => VerificationStatus::NEED_REVISION,
|
||||||
|
DecisionAdmin::REJECTED => VerificationStatus::REJECTED,
|
||||||
|
};
|
||||||
|
|
||||||
|
$verificationRequest->update([
|
||||||
|
'status' => $newStatus,
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
$actionLabel = match ($decision) {
|
$actionLabel = match ($decision) {
|
||||||
DecisionAdmin::APPROVED => 'disetujui',
|
DecisionAdmin::APPROVED => 'disetujui',
|
||||||
@ -286,6 +321,7 @@ protected function processReview(int $requestId, DecisionAdmin $decision, ?strin
|
|||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
|
DB::rollBack();
|
||||||
Log::error('Verification processing failed', [
|
Log::error('Verification processing failed', [
|
||||||
'error' => $e->getMessage(),
|
'error' => $e->getMessage(),
|
||||||
'trace' => $e->getTraceAsString(),
|
'trace' => $e->getTraceAsString(),
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
namespace App\Filament\Pages;
|
namespace App\Filament\Pages;
|
||||||
|
|
||||||
use App\Enums\DataChangeStatus;
|
use App\Enums\DataChangeStatus;
|
||||||
|
use App\Enums\VerificationStatus;
|
||||||
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
|
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
|
||||||
use App\Filament\Support\CheerfulNotification;
|
use App\Filament\Support\CheerfulNotification;
|
||||||
use App\Models\Company as CompanyModel;
|
use App\Models\Company as CompanyModel;
|
||||||
@ -37,6 +38,8 @@ class Company extends Page implements HasForms
|
|||||||
|
|
||||||
public array $originalDocuments = [];
|
public array $originalDocuments = [];
|
||||||
|
|
||||||
|
public bool $isVerificationStage = false;
|
||||||
|
|
||||||
protected static string|UnitEnum|null $navigationGroup = 'Kelola';
|
protected static string|UnitEnum|null $navigationGroup = 'Kelola';
|
||||||
|
|
||||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::BuildingOffice2;
|
protected static string|BackedEnum|null $navigationIcon = Heroicon::BuildingOffice2;
|
||||||
@ -63,6 +66,11 @@ public function mount(): void
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->isVerificationStage = in_array($company->verificationRequest?->status, [
|
||||||
|
VerificationStatus::PENDING,
|
||||||
|
VerificationStatus::REJECTED,
|
||||||
|
]) || $company->verificationRequest()->pending()->exists();
|
||||||
|
|
||||||
$this->verificationRequest = $company->verificationRequest()
|
$this->verificationRequest = $company->verificationRequest()
|
||||||
->latest()
|
->latest()
|
||||||
->first();
|
->first();
|
||||||
@ -283,7 +291,8 @@ public function saveAction(): Action
|
|||||||
->label('Alasan')
|
->label('Alasan')
|
||||||
->placeholder('Jelaskan alasan perubahan data ini...')
|
->placeholder('Jelaskan alasan perubahan data ini...')
|
||||||
->autocomplete(false)
|
->autocomplete(false)
|
||||||
->autofocus(),
|
->autofocus()
|
||||||
|
->required(),
|
||||||
]
|
]
|
||||||
: []
|
: []
|
||||||
)
|
)
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
use App\Enums\MediaClassification;
|
use App\Enums\MediaClassification;
|
||||||
use App\Enums\MediaType;
|
use App\Enums\MediaType;
|
||||||
use App\Enums\RoleEnum;
|
use App\Enums\RoleEnum;
|
||||||
|
use App\Enums\VerificationStatus;
|
||||||
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
|
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
|
||||||
use App\Filament\Support\CheerfulNotification;
|
use App\Filament\Support\CheerfulNotification;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
@ -58,6 +59,8 @@ class Media extends Page implements HasForms
|
|||||||
|
|
||||||
public bool $restricted = false;
|
public bool $restricted = false;
|
||||||
|
|
||||||
|
public bool $isVerificationStage = false;
|
||||||
|
|
||||||
protected static ?string $slug = 'manage/media';
|
protected static ?string $slug = 'manage/media';
|
||||||
|
|
||||||
protected static ?string $title = 'Media';
|
protected static ?string $title = 'Media';
|
||||||
@ -84,6 +87,11 @@ public function mount(): void
|
|||||||
|
|
||||||
$this->company = $company;
|
$this->company = $company;
|
||||||
|
|
||||||
|
$this->isVerificationStage = in_array($company?->verificationRequest?->status, [
|
||||||
|
VerificationStatus::PENDING,
|
||||||
|
VerificationStatus::REJECTED,
|
||||||
|
]) || $company->verificationRequest()->pending()->exists();
|
||||||
|
|
||||||
$verificationRequest = $this->company->verificationRequest()
|
$verificationRequest = $this->company->verificationRequest()
|
||||||
->latest()
|
->latest()
|
||||||
->first();
|
->first();
|
||||||
@ -235,10 +243,10 @@ public function saveAction(): Action
|
|||||||
? [
|
? [
|
||||||
Textarea::make('change_reason')
|
Textarea::make('change_reason')
|
||||||
->label('Alasan')
|
->label('Alasan')
|
||||||
->required()
|
|
||||||
->placeholder('Jelaskan alasan perubahan data ini...')
|
->placeholder('Jelaskan alasan perubahan data ini...')
|
||||||
->autocomplete(false)
|
->autocomplete(false)
|
||||||
->autofocus(),
|
->autofocus()
|
||||||
|
->required(),
|
||||||
]
|
]
|
||||||
: []
|
: []
|
||||||
)
|
)
|
||||||
|
|||||||
@ -3,12 +3,13 @@
|
|||||||
namespace App\Filament\Pages;
|
namespace App\Filament\Pages;
|
||||||
|
|
||||||
use App\Enums\VerificationStatus;
|
use App\Enums\VerificationStatus;
|
||||||
|
use App\Filament\Pages\Company as PagesCompany;
|
||||||
|
use App\Filament\Resources\Manage\Journalists\Pages\ManageJournalists;
|
||||||
use App\Filament\Resources\Manage\Partners\PartnerResource;
|
use App\Filament\Resources\Manage\Partners\PartnerResource;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\VerificationRequest;
|
use App\Models\VerificationRequest;
|
||||||
use App\Notifications\BroadcastNotification;
|
use App\Notifications\BroadcastNotification;
|
||||||
use App\Services\VerificationService;
|
|
||||||
use BackedEnum;
|
use BackedEnum;
|
||||||
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
|
use BezhanSalleh\FilamentShield\Traits\HasPageShield;
|
||||||
use Filament\Actions\Action;
|
use Filament\Actions\Action;
|
||||||
@ -19,6 +20,7 @@
|
|||||||
use Filament\Notifications\Notification;
|
use Filament\Notifications\Notification;
|
||||||
use Filament\Pages\Page;
|
use Filament\Pages\Page;
|
||||||
use Filament\Support\Icons\Heroicon;
|
use Filament\Support\Icons\Heroicon;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use UnitEnum;
|
use UnitEnum;
|
||||||
|
|
||||||
class Verification extends Page implements HasActions, HasForms
|
class Verification extends Page implements HasActions, HasForms
|
||||||
@ -41,15 +43,8 @@ class Verification extends Page implements HasActions, HasForms
|
|||||||
|
|
||||||
public ?VerificationRequest $verificationRequest = null;
|
public ?VerificationRequest $verificationRequest = null;
|
||||||
|
|
||||||
protected VerificationService $verificationService;
|
|
||||||
|
|
||||||
protected string $view = 'filament.pages.verification';
|
protected string $view = 'filament.pages.verification';
|
||||||
|
|
||||||
public function boot(): void
|
|
||||||
{
|
|
||||||
$this->verificationService = app(VerificationService::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function mount(): void
|
public function mount(): void
|
||||||
{
|
{
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
@ -69,14 +64,35 @@ public function mount(): void
|
|||||||
*/
|
*/
|
||||||
public function getVerificationProgress(): array
|
public function getVerificationProgress(): array
|
||||||
{
|
{
|
||||||
$progress = $this->verificationService->getVerificationProgress(
|
$isComplete = $this->isDataComplete();
|
||||||
$this->company,
|
$missingData = $this->getMissingData();
|
||||||
$this->verificationRequest
|
$status = $this->verificationRequest?->status;
|
||||||
);
|
|
||||||
|
$progress = [
|
||||||
|
'currentStep' => $this->resolveStep(),
|
||||||
|
'isDataComplete' => $isComplete,
|
||||||
|
'missingData' => $missingData,
|
||||||
|
'canSubmit' => $this->canSubmit(),
|
||||||
|
'verification' => $this->verificationRequest,
|
||||||
|
'status' => [
|
||||||
|
'label' => $status?->getLabel() ?? 'Belum Mengajukan',
|
||||||
|
'color' => $status?->getColor() ?? 'gray',
|
||||||
|
],
|
||||||
|
'isApproved' => $status === VerificationStatus::APPROVED,
|
||||||
|
'isRejected' => $status === VerificationStatus::REJECTED,
|
||||||
|
'isPending' => $status === VerificationStatus::PENDING,
|
||||||
|
'needsRevision' => $status === VerificationStatus::NEED_REVISION,
|
||||||
|
'latestNotes' => $this->getLatestReviewNotes(),
|
||||||
|
'reviewHistory' => $this->getReviewHistory(),
|
||||||
|
'company' => $this->company,
|
||||||
|
'partnerMedia' => $this->company?->partnerMedia,
|
||||||
|
'journalists' => $this->company?->partnerMedia?->journalists ?? collect(),
|
||||||
|
'steps' => $this->getSteps($isComplete),
|
||||||
|
];
|
||||||
|
|
||||||
// Add additional data for view
|
// Add additional data for view
|
||||||
$progress['missingDataButtons'] = $this->verificationService->getMissingDataButtons($this->company);
|
$progress['missingDataButtons'] = $this->getMissingDataButtons();
|
||||||
$progress['alert'] = $this->verificationService->getAlertData($this->verificationRequest);
|
$progress['alert'] = $this->getAlertData();
|
||||||
$progress['lastSubmittedAt'] = $this->verificationRequest?->updated_at?->translatedFormat('l, d M Y H:i');
|
$progress['lastSubmittedAt'] = $this->verificationRequest?->updated_at?->translatedFormat('l, d M Y H:i');
|
||||||
|
|
||||||
return $progress;
|
return $progress;
|
||||||
@ -120,10 +136,7 @@ public function submitVerificationAction(): Action
|
|||||||
|
|
||||||
$isRevision = $this->verificationRequest && $this->verificationRequest->status === VerificationStatus::NEED_REVISION;
|
$isRevision = $this->verificationRequest && $this->verificationRequest->status === VerificationStatus::NEED_REVISION;
|
||||||
|
|
||||||
$this->verificationRequest = $this->verificationService->submitVerification(
|
$this->verificationRequest = $this->submitVerification();
|
||||||
$this->company,
|
|
||||||
$this->verificationRequest
|
|
||||||
);
|
|
||||||
|
|
||||||
Notification::make()
|
Notification::make()
|
||||||
->title('Berhasil Diajukan! 🚀')
|
->title('Berhasil Diajukan! 🚀')
|
||||||
@ -151,6 +164,261 @@ public function submitVerificationAction(): Action
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if all required data is complete for verification
|
||||||
|
*/
|
||||||
|
protected function isDataComplete(): bool
|
||||||
|
{
|
||||||
|
return $this->company !== null
|
||||||
|
&& $this->company->partnerMedia !== null
|
||||||
|
&& $this->company->partnerMedia?->journalists !== null
|
||||||
|
&& $this->company->partnerMedia->journalists->count() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get missing data items for verification
|
||||||
|
*/
|
||||||
|
protected function getMissingData(): array
|
||||||
|
{
|
||||||
|
$missing = [];
|
||||||
|
|
||||||
|
if (! $this->company) {
|
||||||
|
$missing[] = 'Data Perusahaan';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->company && ! $this->company->partnerMedia) {
|
||||||
|
$missing[] = 'Data Media';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->company && $this->company->partnerMedia && ($this->company->partnerMedia?->journalists === null || $this->company->partnerMedia?->journalists?->count() === 0)) {
|
||||||
|
$missing[] = 'Data Jurnalis (minimal 1)';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $missing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if user can submit verification
|
||||||
|
*/
|
||||||
|
protected function canSubmit(): bool
|
||||||
|
{
|
||||||
|
if (! $this->isDataComplete()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No verification yet - can submit
|
||||||
|
if (! $this->verificationRequest) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can resubmit only if status is NEED_REVISION
|
||||||
|
return $this->verificationRequest->status === VerificationStatus::NEED_REVISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the current step based on status
|
||||||
|
*/
|
||||||
|
protected function resolveStep(): int
|
||||||
|
{
|
||||||
|
if (! $this->isDataComplete()) {
|
||||||
|
return 1; // Data belum lengkap
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $this->verificationRequest) {
|
||||||
|
return 1; // Belum submit
|
||||||
|
}
|
||||||
|
|
||||||
|
return match ($this->verificationRequest->status) {
|
||||||
|
VerificationStatus::PENDING,
|
||||||
|
VerificationStatus::NEED_REVISION => 2, // In review or needs revision
|
||||||
|
|
||||||
|
VerificationStatus::APPROVED,
|
||||||
|
VerificationStatus::REJECTED => 3, // Final decision
|
||||||
|
|
||||||
|
default => 1, // Draft / not submitted yet
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the latest review notes
|
||||||
|
*/
|
||||||
|
protected function getLatestReviewNotes(): ?string
|
||||||
|
{
|
||||||
|
if (! $this->verificationRequest) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$latestReview = $this->verificationRequest->reviews()
|
||||||
|
->where(fn ($q) => $q->needRevision()->orWhere(fn ($q) => $q->rejected()))
|
||||||
|
->latest()
|
||||||
|
->first();
|
||||||
|
|
||||||
|
return $latestReview?->note;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all reviews history
|
||||||
|
*/
|
||||||
|
protected function getReviewHistory(): Collection
|
||||||
|
{
|
||||||
|
if (! $this->verificationRequest) {
|
||||||
|
return collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->verificationRequest->reviews()
|
||||||
|
->with('reviewer')
|
||||||
|
->latest()
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit unified verification
|
||||||
|
*/
|
||||||
|
protected function submitVerification(): VerificationRequest
|
||||||
|
{
|
||||||
|
if ($this->verificationRequest && $this->verificationRequest->status === VerificationStatus::NEED_REVISION) {
|
||||||
|
// Resubmit - update existing request
|
||||||
|
$this->verificationRequest->update([
|
||||||
|
'status' => VerificationStatus::PENDING,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->verificationRequest->fresh(['reviews.reviewer']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New submission
|
||||||
|
return VerificationRequest::create([
|
||||||
|
'company_id' => $this->company->id,
|
||||||
|
'submitted_by' => auth()->id(),
|
||||||
|
'status' => VerificationStatus::PENDING,
|
||||||
|
])->load(['reviews.reviewer']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get alert data for verification status
|
||||||
|
*/
|
||||||
|
protected function getAlertData(): ?array
|
||||||
|
{
|
||||||
|
if (! $this->verificationRequest) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = $this->verificationRequest->status;
|
||||||
|
$latestNotes = $this->getLatestReviewNotes();
|
||||||
|
|
||||||
|
if ($status === VerificationStatus::NEED_REVISION && $latestNotes) {
|
||||||
|
return [
|
||||||
|
'type' => 'revision',
|
||||||
|
'icon' => 'exclamation-triangle',
|
||||||
|
'title' => 'Catatan Revisi dari Admin',
|
||||||
|
'message' => $latestNotes,
|
||||||
|
'color' => 'warning',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($status === VerificationStatus::REJECTED && $latestNotes) {
|
||||||
|
return [
|
||||||
|
'type' => 'rejected',
|
||||||
|
'icon' => 'x-circle',
|
||||||
|
'title' => 'Pengajuan Ditolak',
|
||||||
|
'message' => $latestNotes,
|
||||||
|
'color' => 'danger',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($status === VerificationStatus::APPROVED) {
|
||||||
|
return [
|
||||||
|
'type' => 'approved',
|
||||||
|
'icon' => 'check-circle',
|
||||||
|
'title' => 'Verifikasi Diterima',
|
||||||
|
'message' => 'Verifikasi Anda telah diterima dan disetujui oleh admin. Sekarang Anda sudah resmi terverifikasi dan bekerja sama dengan kami!',
|
||||||
|
'color' => 'success',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($status === VerificationStatus::PENDING) {
|
||||||
|
return [
|
||||||
|
'type' => 'pending',
|
||||||
|
'icon' => 'clock',
|
||||||
|
'title' => 'Menunggu Verifikasi',
|
||||||
|
'message' => 'Data Anda sedang dalam proses verifikasi oleh admin. Mohon tunggu.',
|
||||||
|
'color' => 'info',
|
||||||
|
'animate' => true,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get missing data buttons configuration
|
||||||
|
*/
|
||||||
|
protected function getMissingDataButtons(): array
|
||||||
|
{
|
||||||
|
$buttons = [];
|
||||||
|
|
||||||
|
if (! $this->company) {
|
||||||
|
$buttons[] = [
|
||||||
|
'label' => 'Lengkapi Data Perusahaan',
|
||||||
|
'url' => PagesCompany::getUrl(),
|
||||||
|
'icon' => 'building-office-2',
|
||||||
|
'color' => 'warning',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->company && ! $this->company->partnerMedia) {
|
||||||
|
$buttons[] = [
|
||||||
|
'label' => 'Lengkapi Data Media',
|
||||||
|
'url' => Media::getUrl(),
|
||||||
|
'icon' => 'newspaper',
|
||||||
|
'color' => 'warning',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->company && $this->company->partnerMedia && ($this->company->partnerMedia->journalists === null || $this->company->partnerMedia->journalists->count() === 0)) {
|
||||||
|
$buttons[] = [
|
||||||
|
'label' => 'Lengkapi Data Jurnalis',
|
||||||
|
'url' => ManageJournalists::getUrl(),
|
||||||
|
'icon' => 'user-circle',
|
||||||
|
'color' => 'warning',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get steps array for stepper
|
||||||
|
*/
|
||||||
|
protected function getSteps(bool $isComplete): array
|
||||||
|
{
|
||||||
|
$status = $this->verificationRequest?->status;
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'title' => 'Pengajuan',
|
||||||
|
'description' => $isComplete
|
||||||
|
? 'Data sudah lengkap, silakan ajukan verifikasi'
|
||||||
|
: 'Silakan lengkapi data',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => 'Verifikasi',
|
||||||
|
'description' => match ($status) {
|
||||||
|
VerificationStatus::NEED_REVISION => 'Perlu perbaikan data',
|
||||||
|
VerificationStatus::PENDING => 'Sedang diverifikasi admin',
|
||||||
|
default => 'Menunggu pengajuan',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => 'Selesai',
|
||||||
|
'description' => match ($status) {
|
||||||
|
VerificationStatus::APPROVED => 'Verifikasi disetujui',
|
||||||
|
VerificationStatus::REJECTED => 'Verifikasi ditolak',
|
||||||
|
default => 'Menunggu keputusan',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function getViewData(): array
|
public function getViewData(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
|||||||
@ -56,7 +56,7 @@ protected function setUp(): void
|
|||||||
// Notify User
|
// Notify User
|
||||||
$record->user?->notify(new BroadcastNotification([
|
$record->user?->notify(new BroadcastNotification([
|
||||||
'title' => 'Permohonan Perubahan Ditolak 🛑',
|
'title' => 'Permohonan Perubahan Ditolak 🛑',
|
||||||
'body' => "Halo! Mohon maaf, permohonan perubahan data Anda ({$record->change_reason}) ditolak oleh admin. Alasan: {$data['rejection_reason']} 😔",
|
'body' => "Halo! Mohon maaf, permohonan perubahan data Anda untuk {$record->change_reason} ditolak oleh admin. Alasan: {$data['rejection_reason']} 😔",
|
||||||
]));
|
]));
|
||||||
})
|
})
|
||||||
->visible(fn (DataChangeRequest $record): bool => $record->status === DataChangeStatus::PENDING && ! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value))
|
->visible(fn (DataChangeRequest $record): bool => $record->status === DataChangeStatus::PENDING && ! auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value))
|
||||||
|
|||||||
@ -44,13 +44,13 @@ class DataChangesResource extends Resource
|
|||||||
|
|
||||||
protected static ?string $slug = 'manage/data-changes';
|
protected static ?string $slug = 'manage/data-changes';
|
||||||
|
|
||||||
public static function getNavigationBadge(): string
|
public static function getNavigationBadge(): ?string
|
||||||
{
|
{
|
||||||
return static::getModel()::pending()
|
if (auth()->user()->hasRole(RoleEnum::PERUSAHAAN)) {
|
||||||
->when(auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value), function (Builder $query): void {
|
return null;
|
||||||
$query->where('user_id', auth()->id());
|
}
|
||||||
})
|
|
||||||
->count();
|
return static::getModel()::pending()->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function infolist(Schema $schema): Schema
|
public static function infolist(Schema $schema): Schema
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Filament\Resources\Manage\Journalists\Actions;
|
namespace App\Filament\Resources\Manage\Journalists\Actions;
|
||||||
|
|
||||||
use App\Enums\VerificationStatus;
|
|
||||||
use App\Filament\Actions\Cheerful\CreateAction;
|
use App\Filament\Actions\Cheerful\CreateAction;
|
||||||
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
|
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
|
||||||
use App\Filament\Support\CheerfulNotification;
|
use App\Filament\Support\CheerfulNotification;
|
||||||
@ -26,7 +25,7 @@ protected function setUp(): void
|
|||||||
->modalSubmitActionLabel('Simpan')
|
->modalSubmitActionLabel('Simpan')
|
||||||
->modalCancelActionLabel('Batal')
|
->modalCancelActionLabel('Batal')
|
||||||
->successNotification(null)
|
->successNotification(null)
|
||||||
->extraModalFooterActions(fn(CreateAction $action): array => [
|
->extraModalFooterActions(fn (CreateAction $action): array => [
|
||||||
$action->makeModalSubmitAction('createAnother', arguments: ['another' => true])
|
$action->makeModalSubmitAction('createAnother', arguments: ['another' => true])
|
||||||
->label('Simpan dan Tambah Lagi'),
|
->label('Simpan dan Tambah Lagi'),
|
||||||
])
|
])
|
||||||
@ -100,10 +99,10 @@ protected function setUp(): void
|
|||||||
|
|
||||||
User::superAdmin()
|
User::superAdmin()
|
||||||
->get()
|
->get()
|
||||||
->each(function ($admin) use ($dataChangeRequest): void {
|
->each(function ($admin) use ($dataChangeRequest, $user): void {
|
||||||
$admin->notify(new BroadcastNotification([
|
$admin->notify(new BroadcastNotification([
|
||||||
'title' => 'Ada Penambahan Jurnalis Baru ✨',
|
'title' => 'Ada Penambahan Jurnalis Baru ✨',
|
||||||
'body' => 'Halooo Admin! 👋 ' . $user->name . ' baru saja menambahkan jurnalis baru. Yuk, cek detailnya! 🚀',
|
'body' => 'Halooo Admin! 👋 '.$user->name.' baru saja menambahkan jurnalis baru. Yuk, cek detailnya! 🚀',
|
||||||
'action' => [
|
'action' => [
|
||||||
Action::make('view')
|
Action::make('view')
|
||||||
->label('Lihat')
|
->label('Lihat')
|
||||||
|
|||||||
@ -23,9 +23,9 @@ protected function setUp(): void
|
|||||||
|
|
||||||
$this->successNotification(null);
|
$this->successNotification(null);
|
||||||
|
|
||||||
$this->modalHeading(fn() => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED ? 'Ajukan Penghapusan Jurnalis' : 'Hapus Jurnalis');
|
$this->modalHeading(fn () => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED ? 'Ajukan Penghapusan Jurnalis' : 'Hapus Jurnalis');
|
||||||
|
|
||||||
$this->schema(fn() => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED ? [
|
$this->schema(fn () => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED ? [
|
||||||
Textarea::make('deletion_reason')
|
Textarea::make('deletion_reason')
|
||||||
->label('Alasan Penghapusan')
|
->label('Alasan Penghapusan')
|
||||||
->placeholder('Jelaskan alasan mengapa jurnalis ini dihapus...')
|
->placeholder('Jelaskan alasan mengapa jurnalis ini dihapus...')
|
||||||
@ -69,7 +69,7 @@ protected function setUp(): void
|
|||||||
->each(function ($admin) use ($user, $record, $dataChangeRequest): void {
|
->each(function ($admin) use ($user, $record, $dataChangeRequest): void {
|
||||||
$admin->notify(new BroadcastNotification([
|
$admin->notify(new BroadcastNotification([
|
||||||
'title' => 'Ada Pengajuan Penghapusan Jurnalis ✨',
|
'title' => 'Ada Pengajuan Penghapusan Jurnalis ✨',
|
||||||
'body' => 'Halooo Admin! 👋 ' . $user->name . ' baru saja mengajukan penghapusan jurnalis ' . $record->name . '. Yuk, cek detailnya! 🚀',
|
'body' => 'Halooo Admin! 👋 '.$user->name.' baru saja mengajukan penghapusan jurnalis '.$record->name.'. Yuk, cek detailnya! 🚀',
|
||||||
'action' => [
|
'action' => [
|
||||||
Action::make('view')
|
Action::make('view')
|
||||||
->label('Lihat')
|
->label('Lihat')
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
use App\Enums\DataChangeStatus;
|
use App\Enums\DataChangeStatus;
|
||||||
use App\Enums\RoleEnum;
|
use App\Enums\RoleEnum;
|
||||||
use App\Enums\VerificationStatus;
|
|
||||||
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
|
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
|
||||||
use App\Filament\Support\CheerfulNotification;
|
use App\Filament\Support\CheerfulNotification;
|
||||||
use App\Models\DataChangeRequest;
|
use App\Models\DataChangeRequest;
|
||||||
@ -143,10 +142,10 @@ protected function setUp(): void
|
|||||||
|
|
||||||
User::superAdmin()
|
User::superAdmin()
|
||||||
->get()
|
->get()
|
||||||
->each(function ($admin) use ($dataChangeRequest): void {
|
->each(function ($admin) use ($dataChangeRequest, $user): void {
|
||||||
$admin->notify(new BroadcastNotification([
|
$admin->notify(new BroadcastNotification([
|
||||||
'title' => 'Ada Pengajuan Perubahan Jurnalis ✨',
|
'title' => 'Ada Pengajuan Perubahan Jurnalis ✨',
|
||||||
'body' => 'Halooo Admin! 👋 ' . $user->name . ' baru saja mengajukan perubahan data jurnalis. Yuk, cek detailnya! 🚀',
|
'body' => 'Halooo Admin! 👋 '.$user->name.' baru saja mengajukan perubahan data jurnalis. Yuk, cek detailnya! 🚀',
|
||||||
'action' => [
|
'action' => [
|
||||||
Action::make('view')
|
Action::make('view')
|
||||||
->label('Lihat')
|
->label('Lihat')
|
||||||
@ -195,7 +194,7 @@ private function performSave(Journalist $record, array $data): void
|
|||||||
];
|
];
|
||||||
|
|
||||||
$existingMedia = $record->getMedia('journalists');
|
$existingMedia = $record->getMedia('journalists');
|
||||||
$existingPaths = $existingMedia->map(fn($m) => $m->getPathRelativeToRoot())->toArray();
|
$existingPaths = $existingMedia->map(fn ($m) => $m->getPathRelativeToRoot())->toArray();
|
||||||
|
|
||||||
foreach ($documents as $field) {
|
foreach ($documents as $field) {
|
||||||
if (empty($data[$field])) {
|
if (empty($data[$field])) {
|
||||||
|
|||||||
@ -134,7 +134,7 @@ public static function form(Schema $schema): Schema
|
|||||||
->rows(3)
|
->rows(3)
|
||||||
->required(),
|
->required(),
|
||||||
])
|
])
|
||||||
->visible(fn () => auth()->user()->company?->status === VerificationStatus::APPROVED && auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)),
|
->visible(fn () => auth()->user()->company?->verificationRequest?->status === VerificationStatus::APPROVED && auth()->user()->hasRole(RoleEnum::PERUSAHAAN->value)),
|
||||||
])
|
])
|
||||||
->columns(1);
|
->columns(1);
|
||||||
}
|
}
|
||||||
@ -177,14 +177,24 @@ public static function table(Table $table): Table
|
|||||||
->native(false)
|
->native(false)
|
||||||
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
->visible(fn () => auth()->user()?->hasRole('Developer')),
|
||||||
])
|
])
|
||||||
|
->checkIfRecordIsSelectableUsing(
|
||||||
|
fn () => ! (
|
||||||
|
in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) ||
|
||||||
|
auth()->user()->company?->verificationRequest()->pending()->exists()
|
||||||
|
)
|
||||||
|
)
|
||||||
->recordActions([
|
->recordActions([
|
||||||
EditJournalistAction::make('edit'),
|
EditJournalistAction::make('edit')
|
||||||
|
->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||||
|
|
||||||
DeleteJournalistAction::make('delete'),
|
DeleteJournalistAction::make('delete')
|
||||||
|
->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||||
|
|
||||||
ForceDeleteAction::make(),
|
ForceDeleteAction::make()
|
||||||
|
->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||||
|
|
||||||
RestoreAction::make(),
|
RestoreAction::make()
|
||||||
|
->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||||
])
|
])
|
||||||
->toolbarActions([
|
->toolbarActions([
|
||||||
BulkActionGroup::make([
|
BulkActionGroup::make([
|
||||||
@ -193,7 +203,7 @@ public static function table(Table $table): Table
|
|||||||
ForceDeleteBulkAction::make(),
|
ForceDeleteBulkAction::make(),
|
||||||
|
|
||||||
RestoreBulkAction::make(),
|
RestoreBulkAction::make(),
|
||||||
]),
|
])->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||||
])
|
])
|
||||||
->emptyStateIcon(Heroicon::Identification)
|
->emptyStateIcon(Heroicon::Identification)
|
||||||
->emptyStateDescription('Setelah Anda membubat data pertama, maka akan muncul disini.')
|
->emptyStateDescription('Setelah Anda membubat data pertama, maka akan muncul disini.')
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
namespace App\Filament\Resources\Manage\Journalists\Pages;
|
namespace App\Filament\Resources\Manage\Journalists\Pages;
|
||||||
|
|
||||||
use App\Enums\RoleEnum;
|
use App\Enums\RoleEnum;
|
||||||
|
use App\Enums\VerificationStatus;
|
||||||
use App\Filament\Resources\Manage\Journalists\Actions\CreateJournalistAction;
|
use App\Filament\Resources\Manage\Journalists\Actions\CreateJournalistAction;
|
||||||
use App\Filament\Resources\Manage\Journalists\JournalistResource;
|
use App\Filament\Resources\Manage\Journalists\JournalistResource;
|
||||||
use Filament\Resources\Pages\ManageRecords;
|
use Filament\Resources\Pages\ManageRecords;
|
||||||
@ -20,7 +21,8 @@ protected function getHeaderActions(): array
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
CreateJournalistAction::make(),
|
CreateJournalistAction::make()
|
||||||
|
->visible(fn () => ! (in_array(auth()->user()->company?->verificationRequest?->status, [VerificationStatus::PENDING, VerificationStatus::REJECTED]) || auth()->user()->company?->verificationRequest()->pending()->exists())),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,401 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Services;
|
|
||||||
|
|
||||||
use App\Enums\DecisionAdmin;
|
|
||||||
use App\Enums\VerificationStatus;
|
|
||||||
use App\Filament\Pages\Company as PagesCompany;
|
|
||||||
use App\Filament\Pages\Media;
|
|
||||||
use App\Filament\Resources\Manage\Journalists\Pages\ManageJournalists;
|
|
||||||
use App\Models\Company;
|
|
||||||
use App\Models\VerificationRequest;
|
|
||||||
use App\Models\VerificationReview;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
class VerificationService
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Check if all required data is complete for verification
|
|
||||||
*/
|
|
||||||
public function isDataComplete(?Company $company): bool
|
|
||||||
{
|
|
||||||
return $company !== null
|
|
||||||
&& $company->partnerMedia !== null
|
|
||||||
&& $company->partnerMedia?->journalists !== null
|
|
||||||
&& $company->partnerMedia->journalists->count() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get missing data items for verification
|
|
||||||
*/
|
|
||||||
public function getMissingData(?Company $company): array
|
|
||||||
{
|
|
||||||
$missing = [];
|
|
||||||
|
|
||||||
if (! $company) {
|
|
||||||
$missing[] = 'Data Perusahaan';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($company && ! $company->partnerMedia) {
|
|
||||||
$missing[] = 'Data Media';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($company && $company->partnerMedia && ($company->partnerMedia?->journalists === null || $company->partnerMedia?->journalists?->count() === 0)) {
|
|
||||||
$missing[] = 'Data Jurnalis (minimal 1)';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $missing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if user can submit verification
|
|
||||||
*/
|
|
||||||
public function canSubmit(?Company $company, ?VerificationRequest $verificationRequest): bool
|
|
||||||
{
|
|
||||||
if (! $this->isDataComplete($company)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No verification yet - can submit
|
|
||||||
if (! $verificationRequest) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can resubmit only if status is NEED_REVISION
|
|
||||||
return $verificationRequest->status === VerificationStatus::NEED_REVISION;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine the current step based on status
|
|
||||||
*/
|
|
||||||
public function resolveStep(?Company $company, ?VerificationRequest $verificationRequest): int
|
|
||||||
{
|
|
||||||
if (! $this->isDataComplete($company)) {
|
|
||||||
return 1; // Data belum lengkap
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $verificationRequest) {
|
|
||||||
return 1; // Belum submit
|
|
||||||
}
|
|
||||||
|
|
||||||
return match ($verificationRequest->status) {
|
|
||||||
VerificationStatus::PENDING,
|
|
||||||
VerificationStatus::NEED_REVISION => 2, // In review or needs revision
|
|
||||||
|
|
||||||
VerificationStatus::APPROVED,
|
|
||||||
VerificationStatus::REJECTED => 3, // Final decision
|
|
||||||
|
|
||||||
default => 1, // Draft / not submitted yet
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the latest review notes
|
|
||||||
*/
|
|
||||||
public function getLatestReviewNotes(?VerificationRequest $verificationRequest): ?string
|
|
||||||
{
|
|
||||||
if (! $verificationRequest) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$latestReview = $verificationRequest->reviews()
|
|
||||||
->where(fn ($q) => $q->needRevision()->orWhere(fn ($q) => $q->rejected()))
|
|
||||||
->latest()
|
|
||||||
->first();
|
|
||||||
|
|
||||||
return $latestReview?->note;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all reviews history
|
|
||||||
*/
|
|
||||||
public function getReviewHistory(?VerificationRequest $verificationRequest): Collection
|
|
||||||
{
|
|
||||||
if (! $verificationRequest) {
|
|
||||||
return collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $verificationRequest->reviews()
|
|
||||||
->with('reviewer')
|
|
||||||
->latest()
|
|
||||||
->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get unified verification progress data
|
|
||||||
*/
|
|
||||||
public function getVerificationProgress(?Company $company, ?VerificationRequest $verificationRequest): array
|
|
||||||
{
|
|
||||||
$currentStep = $this->resolveStep($company, $verificationRequest);
|
|
||||||
$isComplete = $this->isDataComplete($company);
|
|
||||||
$missingData = $this->getMissingData($company);
|
|
||||||
|
|
||||||
$status = $verificationRequest?->status;
|
|
||||||
|
|
||||||
return [
|
|
||||||
'currentStep' => $currentStep,
|
|
||||||
'isDataComplete' => $isComplete,
|
|
||||||
'missingData' => $missingData,
|
|
||||||
'canSubmit' => $this->canSubmit($company, $verificationRequest),
|
|
||||||
'verification' => $verificationRequest,
|
|
||||||
'status' => [
|
|
||||||
'label' => $status?->getLabel() ?? 'Belum Mengajukan',
|
|
||||||
'color' => $status?->getColor() ?? 'gray',
|
|
||||||
],
|
|
||||||
'isApproved' => $status === VerificationStatus::APPROVED,
|
|
||||||
'isRejected' => $status === VerificationStatus::REJECTED,
|
|
||||||
'isPending' => $status === VerificationStatus::PENDING,
|
|
||||||
'needsRevision' => $status === VerificationStatus::NEED_REVISION,
|
|
||||||
'latestNotes' => $this->getLatestReviewNotes($verificationRequest),
|
|
||||||
'reviewHistory' => $this->getReviewHistory($verificationRequest),
|
|
||||||
'company' => $company,
|
|
||||||
'partnerMedia' => $company?->partnerMedia,
|
|
||||||
'journalists' => $company?->partnerMedia?->journalists ?? collect(),
|
|
||||||
'steps' => $this->getSteps($verificationRequest, $isComplete, $missingData),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get steps array for stepper
|
|
||||||
*/
|
|
||||||
protected function getSteps(?VerificationRequest $verificationRequest, bool $isComplete, array $missingData): array
|
|
||||||
{
|
|
||||||
$status = $verificationRequest?->status;
|
|
||||||
|
|
||||||
return [
|
|
||||||
[
|
|
||||||
'title' => 'Pengajuan',
|
|
||||||
'description' => $isComplete
|
|
||||||
? 'Data sudah lengkap, silakan ajukan verifikasi'
|
|
||||||
: 'Silakan lengkapi data',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'title' => 'Verifikasi',
|
|
||||||
'description' => match ($status) {
|
|
||||||
VerificationStatus::NEED_REVISION => 'Perlu perbaikan data',
|
|
||||||
VerificationStatus::PENDING => 'Sedang diverifikasi admin',
|
|
||||||
default => 'Menunggu pengajuan',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'title' => 'Selesai',
|
|
||||||
'description' => match ($status) {
|
|
||||||
VerificationStatus::APPROVED => 'Verifikasi disetujui',
|
|
||||||
VerificationStatus::REJECTED => 'Verifikasi ditolak',
|
|
||||||
default => 'Menunggu keputusan',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submit unified verification
|
|
||||||
*/
|
|
||||||
public function submitVerification(Company $company, ?VerificationRequest $existingRequest): VerificationRequest
|
|
||||||
{
|
|
||||||
if ($existingRequest && $existingRequest->status === VerificationStatus::NEED_REVISION) {
|
|
||||||
// Resubmit - update existing request
|
|
||||||
$existingRequest->update([
|
|
||||||
'status' => VerificationStatus::PENDING,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return $existingRequest->fresh(['reviews.reviewer']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// New submission
|
|
||||||
return VerificationRequest::create([
|
|
||||||
'company_id' => $company->id,
|
|
||||||
'submitted_by' => auth()->id(),
|
|
||||||
'status' => VerificationStatus::PENDING,
|
|
||||||
])->load(['reviews.reviewer']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process review decision - unified for Company, Media, and Journalists
|
|
||||||
*/
|
|
||||||
public function processReview(VerificationRequest $verificationRequest, DecisionAdmin $decision, ?string $note): void
|
|
||||||
{
|
|
||||||
$verificationRequest->load(['company.partnerMedia.journalists']);
|
|
||||||
|
|
||||||
DB::beginTransaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Create review record
|
|
||||||
VerificationReview::create([
|
|
||||||
'verification_request_id' => $verificationRequest->id,
|
|
||||||
'reviewer_id' => auth()->id(),
|
|
||||||
'decision' => $decision,
|
|
||||||
'note' => $note,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Update verification request status
|
|
||||||
$newStatus = match ($decision) {
|
|
||||||
DecisionAdmin::APPROVED => VerificationStatus::APPROVED,
|
|
||||||
DecisionAdmin::NEED_REVISION => VerificationStatus::NEED_REVISION,
|
|
||||||
DecisionAdmin::REJECTED => VerificationStatus::REJECTED,
|
|
||||||
};
|
|
||||||
|
|
||||||
$verificationRequest->update([
|
|
||||||
'status' => $newStatus,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Update Company status
|
|
||||||
$company = $verificationRequest->company;
|
|
||||||
if ($company) {
|
|
||||||
$company->update(['status' => $newStatus]);
|
|
||||||
|
|
||||||
// Update Media status
|
|
||||||
$media = $company->partnerMedia;
|
|
||||||
if ($media) {
|
|
||||||
$media->update(['status' => $newStatus]);
|
|
||||||
|
|
||||||
// Update all Journalists status
|
|
||||||
$media->journalists()->update(['status' => $newStatus]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DB::commit();
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
Log::error('Verification review processing failed', [
|
|
||||||
'error' => $e->getMessage(),
|
|
||||||
'trace' => $e->getTraceAsString(),
|
|
||||||
'request_id' => $verificationRequest->id,
|
|
||||||
'decision' => $decision->value,
|
|
||||||
]);
|
|
||||||
|
|
||||||
DB::rollBack();
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get company name from verification request
|
|
||||||
*/
|
|
||||||
public function getCompanyName(VerificationRequest $request): string
|
|
||||||
{
|
|
||||||
return $request->company?->name ?? 'Data tidak ditemukan';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get verification summary data for admin
|
|
||||||
*/
|
|
||||||
public function getVerificationSummary(VerificationRequest $request): array
|
|
||||||
{
|
|
||||||
$company = $request->company;
|
|
||||||
$media = $company?->partnerMedia;
|
|
||||||
$journalists = $media?->journalists ?? collect();
|
|
||||||
|
|
||||||
return [
|
|
||||||
'company' => [
|
|
||||||
'name' => $company?->name ?? 'Belum diisi',
|
|
||||||
'email' => $company?->email ?? '-',
|
|
||||||
'exists' => $company !== null,
|
|
||||||
],
|
|
||||||
'media' => [
|
|
||||||
'name' => $media?->name ?? 'Belum diisi',
|
|
||||||
'type' => $media?->type?->getLabel() ?? '-',
|
|
||||||
'exists' => $media !== null,
|
|
||||||
],
|
|
||||||
'journalists' => [
|
|
||||||
'count' => $journalists->count(),
|
|
||||||
'names' => $journalists->pluck('name')->take(3)->toArray(),
|
|
||||||
'exists' => $journalists->count() > 0,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get alert data for verification status
|
|
||||||
*/
|
|
||||||
public function getAlertData(?VerificationRequest $verificationRequest): ?array
|
|
||||||
{
|
|
||||||
if (! $verificationRequest) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$status = $verificationRequest->status;
|
|
||||||
$latestNotes = $this->getLatestReviewNotes($verificationRequest);
|
|
||||||
|
|
||||||
if ($status === VerificationStatus::NEED_REVISION && $latestNotes) {
|
|
||||||
return [
|
|
||||||
'type' => 'revision',
|
|
||||||
'icon' => 'exclamation-triangle',
|
|
||||||
'title' => 'Catatan Revisi dari Admin',
|
|
||||||
'message' => $latestNotes,
|
|
||||||
'color' => 'warning',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($status === VerificationStatus::REJECTED && $latestNotes) {
|
|
||||||
return [
|
|
||||||
'type' => 'rejected',
|
|
||||||
'icon' => 'x-circle',
|
|
||||||
'title' => 'Pengajuan Ditolak',
|
|
||||||
'message' => $latestNotes,
|
|
||||||
'color' => 'danger',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($status === VerificationStatus::APPROVED) {
|
|
||||||
return [
|
|
||||||
'type' => 'approved',
|
|
||||||
'icon' => 'check-circle',
|
|
||||||
'title' => 'Verifikasi Diterima',
|
|
||||||
'message' => 'Verifikasi Anda telah diterima dan disetujui oleh admin. Sekarang Anda sudah resmi terverifikasi dan bekerja sama dengan kami!',
|
|
||||||
'color' => 'success',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($status === VerificationStatus::PENDING) {
|
|
||||||
return [
|
|
||||||
'type' => 'pending',
|
|
||||||
'icon' => 'clock',
|
|
||||||
'title' => 'Menunggu Verifikasi',
|
|
||||||
'message' => 'Data Anda sedang dalam proses verifikasi oleh admin. Mohon tunggu.',
|
|
||||||
'color' => 'info',
|
|
||||||
'animate' => true,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get missing data buttons configuration
|
|
||||||
*/
|
|
||||||
public function getMissingDataButtons(?Company $company): array
|
|
||||||
{
|
|
||||||
$buttons = [];
|
|
||||||
|
|
||||||
if (! $company) {
|
|
||||||
$buttons[] = [
|
|
||||||
'label' => 'Lengkapi Data Perusahaan',
|
|
||||||
'url' => PagesCompany::getUrl(),
|
|
||||||
'icon' => 'building-office-2',
|
|
||||||
'color' => 'warning',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($company && ! $company->partnerMedia) {
|
|
||||||
$buttons[] = [
|
|
||||||
'label' => 'Lengkapi Data Media',
|
|
||||||
'url' => Media::getUrl(),
|
|
||||||
'icon' => 'newspaper',
|
|
||||||
'color' => 'warning',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($company && $company->partnerMedia && ($company->partnerMedia->journalists === null || $company->partnerMedia->journalists->count() === 0)) {
|
|
||||||
$buttons[] = [
|
|
||||||
'label' => 'Lengkapi Data Jurnalis',
|
|
||||||
'url' => ManageJournalists::getUrl(),
|
|
||||||
'icon' => 'user-circle',
|
|
||||||
'color' => 'warning',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $buttons;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,8 +2,10 @@
|
|||||||
<form wire:submit.prevent="save">
|
<form wire:submit.prevent="save">
|
||||||
{{ $this->form }}
|
{{ $this->form }}
|
||||||
|
|
||||||
|
@if (!$this->isVerificationStage)
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
{{ $this->saveAction() }}
|
{{ $this->saveAction() }}
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
</form>
|
</form>
|
||||||
</x-filament-panels::page>
|
</x-filament-panels::page>
|
||||||
|
|||||||
@ -32,9 +32,11 @@ class="dark:text-gray-400">
|
|||||||
<form wire:submit.prevent="save">
|
<form wire:submit.prevent="save">
|
||||||
{{ $this->form }}
|
{{ $this->form }}
|
||||||
|
|
||||||
|
@if (!$this->isVerificationStage)
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
{{ $this->saveAction() }}
|
{{ $this->saveAction() }}
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
</form>
|
</form>
|
||||||
@endif
|
@endif
|
||||||
</x-filament-panels::page>
|
</x-filament-panels::page>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user