Files
My-KOPKB/be/Modules/MembershipApplication/Http/Controllers/MembershipApplicationController.php
T
ismailmasseran 18c0d268b1
Build Docker Image / build-backend (push) Successful in 52s
Build Docker Image / build-frontend (push) Successful in 32s
DONE: update logo to original official logo, update letterhead and letterfooter layout (#8)
Co-authored-by: ISMAIL MASSERAN <topaz@Mac.dlinkrouter.local>
Reviewed-on: #8
2026-07-07 14:45:20 +08:00

328 lines
12 KiB
PHP

<?php
namespace Modules\MembershipApplication\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Services\DocumentService;
use App\Services\LetterService;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Modules\MembershipApplication\Entities\MembershipApplication;
use Modules\MembershipApplication\Enums\ApplicationStatus;
use Modules\MembershipApplication\Enums\BoardDecision;
use Modules\MembershipApplication\Enums\BoardResult;
use Modules\MembershipApplication\Enums\ManagementDecision;
use Modules\MembershipApplication\Http\Requests\AssignReferencesRequest;
use Modules\MembershipApplication\Http\Requests\BatchCompleteRequest;
use Modules\MembershipApplication\Http\Requests\BoardReviewRequest;
use Modules\MembershipApplication\Http\Requests\CompleteMembershipApplicationRequest;
use Modules\MembershipApplication\Http\Requests\GenerateResultLetterRequest;
use Modules\MembershipApplication\Http\Requests\ManagementReviewRequest;
use Modules\MembershipApplication\Http\Requests\UpdateMembershipApplicationRequest;
use Modules\MembershipApplication\Http\Requests\UploadMembershipApplicationDocumentRequest;
use Modules\MembershipApplication\Services\MembershipApplicationService;
use Modules\MembershipApplication\Transformers\MembershipApplicationDocumentResource;
use Modules\MembershipApplication\Transformers\MembershipApplicationListResource;
use Modules\MembershipApplication\Transformers\MembershipApplicationResource;
use Symfony\Component\HttpFoundation\StreamedResponse;
class MembershipApplicationController extends Controller
{
use AuthorizesRequests;
public function __construct(
protected MembershipApplicationService $membershipApplicationService,
protected DocumentService $documentService,
protected LetterService $letterService,
) {}
public function index(Request $request): JsonResponse
{
$this->authorize('viewAny', MembershipApplication::class);
$perPage = min((int) $request->get('per_page', 10), 100);
$search = (string) ($request->get('search', '') ?? '');
$status = $request->get('status');
$sortBy = (string) ($request->get('sort_by', 'submitted_at') ?? 'submitted_at');
$sortOrder = (string) ($request->get('sort_order', 'desc') ?? 'desc');
$applications = $this->membershipApplicationService->getPaginatedList(
$perPage,
$search,
$status,
$sortBy,
$sortOrder
);
return response()->json([
'success' => true,
'data' => MembershipApplicationListResource::collection($applications->items()),
'pagination' => [
'current_page' => $applications->currentPage(),
'per_page' => $applications->perPage(),
'total' => $applications->total(),
'last_page' => $applications->lastPage(),
'from' => $applications->firstItem(),
'to' => $applications->lastItem(),
'has_more_pages' => $applications->hasMorePages(),
],
]);
}
public function show(MembershipApplication $membershipApplication): JsonResponse
{
$this->authorize('view', $membershipApplication);
$application = $this->membershipApplicationService->getByIdWithRelations($membershipApplication->id);
if (! $application) {
return response()->json([
'success' => false,
'message' => 'Permohonan tidak dijumpai.',
], 404);
}
return response()->json([
'success' => true,
'data' => new MembershipApplicationResource($application),
]);
}
public function update(UpdateMembershipApplicationRequest $request, MembershipApplication $membershipApplication): JsonResponse
{
$this->authorize('update', $membershipApplication);
$application = $this->membershipApplicationService->update(
$membershipApplication,
$request->validated(),
);
return response()->json([
'success' => true,
'message' => 'Permohonan keahlian berjaya dikemaskini.',
'data' => new MembershipApplicationResource($application),
]);
}
public function uploadDocument(UploadMembershipApplicationDocumentRequest $request, MembershipApplication $membershipApplication): JsonResponse
{
$this->authorize('update', $membershipApplication);
$application = $this->membershipApplicationService->uploadDocument(
$membershipApplication,
$request->validated('type'),
$request->file('file'),
);
return response()->json([
'success' => true,
'message' => 'Dokumen berjaya dimuat naik.',
'data' => new MembershipApplicationResource($application),
]);
}
public function managementReview(ManagementReviewRequest $request, MembershipApplication $membershipApplication): JsonResponse {
$this->authorize('managementReview', $membershipApplication);
$application = $this->membershipApplicationService->managementReview(
$membershipApplication,
ManagementDecision::from($request->validated('decision')),
$request->validated('remarks'),
$request->user()
);
$message = $application->status === ApplicationStatus::PendingBoard
? 'Permohonan diluluskan dan dihantar ke lembaga.'
: 'Permohonan ditolak.';
return response()->json([
'success' => true,
'message' => $message,
'data' => new MembershipApplicationResource($application),
]);
}
public function boardReview(BoardReviewRequest $request, MembershipApplication $membershipApplication): JsonResponse {
$this->authorize('boardReview', $membershipApplication);
$application = $this->membershipApplicationService->boardReview(
$membershipApplication,
BoardDecision::from($request->validated('decision')),
$request->validated('remarks'),
$request->user()
);
$message = $application->board_result === BoardResult::Pass->value
? 'Permohonan lulus semakan lembaga.'
: 'Permohonan gagal semakan lembaga.';
return response()->json([
'success' => true,
'message' => $message,
'data' => new MembershipApplicationResource($application),
]);
}
public function assignReferences(AssignReferencesRequest $request, MembershipApplication $membershipApplication): JsonResponse {
$this->authorize('assignReferences', $membershipApplication);
$application = $this->membershipApplicationService->assignReferences(
$membershipApplication,
$request->validated(),
$request->user()
);
return response()->json([
'success' => true,
'message' => 'Pencadang dan penyokong berjaya dikemaskini.',
'data' => new MembershipApplicationResource($application),
]);
}
public function complete(CompleteMembershipApplicationRequest $request, MembershipApplication $membershipApplication): JsonResponse
{
$this->authorize('complete', $membershipApplication);
$application = $this->membershipApplicationService->complete(
$membershipApplication,
$request->user(),
$request->validated('board_meeting_reference'),
$request->validated('board_meeting_date'),
);
$message = $application->board_result === BoardResult::Pass->value
? 'Permohonan selesai. Surat keputusan dijana, akaun ahli dicipta dan e-mel dihantar.'
: 'Permohonan selesai. Surat keputusan dijana dan e-mel dihantar.';
return response()->json([
'success' => true,
'message' => $message,
'data' => new MembershipApplicationResource($application),
]);
}
public function batchComplete(BatchCompleteRequest $request): JsonResponse
{
$this->authorize('completeBatch', MembershipApplication::class);
$result = $this->membershipApplicationService->completeBatch(
$request->validated('application_ids'),
$request->user(),
$request->validated('board_meeting_reference'),
$request->validated('board_meeting_date'),
);
$succeededCount = count($result['succeeded']);
$failedCount = count($result['failed']);
if ($succeededCount === 0) {
return response()->json([
'success' => false,
'message' => 'Tiada permohonan berjaya diselesaikan.',
'data' => [
'succeeded' => [],
'failed' => $result['failed'],
],
], 422);
}
$message = $failedCount > 0
? "{$succeededCount} permohonan berjaya, {$failedCount} gagal."
: "{$succeededCount} permohonan berjaya diselesaikan.";
return response()->json([
'success' => true,
'message' => $message,
'data' => [
'succeeded' => MembershipApplicationResource::collection($result['succeeded']),
'failed' => $result['failed'],
],
]);
}
public function downloadDocument(MembershipApplication $membershipApplication, string $documentId): StreamedResponse {
$this->authorize('view', $membershipApplication);
$document = $membershipApplication->documents()->findOrFail($documentId);
return $this->documentService->downloadDocument($document->id);
}
public function deleteDocument(MembershipApplication $membershipApplication, string $documentId): JsonResponse
{
$this->authorize('update', $membershipApplication);
$application = $this->membershipApplicationService->deleteDocument(
$membershipApplication,
$documentId,
);
return response()->json([
'success' => true,
'message' => 'Lampiran pentadbir berjaya dipadam.',
'data' => new MembershipApplicationResource($application),
]);
}
public function generateResultLetter(GenerateResultLetterRequest $request, MembershipApplication $membershipApplication,): JsonResponse {
$this->authorize('generateResultLetter', $membershipApplication);
$application = $this->membershipApplicationService->generateResultLetter(
$membershipApplication,
$request->validated('board_meeting_reference'),
$request->validated('board_meeting_date'),
);
$resultLetter = $application->documents
->firstWhere('type', MembershipApplication::RESULT_LETTER_DOCUMENT_TYPE);
return response()->json([
'success' => true,
'message' => 'Surat keputusan berjaya dijana.',
'data' => [
'application' => new MembershipApplicationResource($application),
'document' => $resultLetter
? new MembershipApplicationDocumentResource($resultLetter)
: null,
],
]);
}
public function approvedLetter(Request $request, MembershipApplication $membershipApplication): Response
{
$this->authorize('view', $membershipApplication);
$application = $this->membershipApplicationService->getByIdWithRelations($membershipApplication->id);
if (! $application) {
abort(404, 'Permohonan tidak dijumpai.');
}
$boardMeetingReference = (string) $request->query(
'board_meeting_reference',
'Mesyuarat Lembaga',
);
$boardMeetingDate = (string) $request->query(
'board_meeting_date',
now()->toDateString(),
);
$view = 'membershipapplication::pdf.approved-letter';
$data = $this->membershipApplicationService->getResultLetterViewData(
$application,
$boardMeetingReference,
$boardMeetingDate,
);
$format = $request->query('format', 'html');
$filename = 'surat-keputusan-'.$application->application_number.'.pdf';
if ($format === 'pdf') {
return $this->letterService->pdfResponse($view, $data, $filename);
}
return $this->letterService->htmlResponse($view, $data);
}
}