authorize('viewAny', SalaryContribution::class); $query = SalaryDeductionBatch::query()->orderByDesc('year')->orderByDesc('month'); if ($status = $request->query('status')) { $query->where('status', $status); } $batches = $query->paginate(min((int) $request->get('per_page', 10), 1000)); return response()->json([ 'success' => true, 'data' => SalaryDeductionBatchResource::collection($batches->items()), 'pagination' => [ 'current_page' => $batches->currentPage(), 'per_page' => $batches->perPage(), 'total' => $batches->total(), 'last_page' => $batches->lastPage(), 'from' => $batches->firstItem(), 'to' => $batches->lastItem(), 'has_more_pages' => $batches->hasMorePages(), ], 'message' => 'Batch potongan gaji berjaya dimuatkan', ]); } public function show(string $id): JsonResponse { $this->authorize('view', SalaryContribution::class); $batch = SalaryDeductionBatch::query() ->with([ 'details.user:id,name,email,ic_number', 'details.investmentType:id,code,name', 'details.investment:id,reference_no,status,amount', 'uploadedBy:id,name,email', 'verifiedBy:id,name,email', ]) ->find($id); if (! $batch) { return response()->json([ 'success' => false, 'message' => 'Batch potongan gaji tidak dijumpai.', ], 404); } return response()->json([ 'success' => true, 'data' => new SalaryDeductionBatchResource($batch), 'message' => 'Batch potongan gaji berjaya dimuatkan', ]); } public function store(UploadSalaryDeductionBatchRequest $request): JsonResponse { $this->authorize('create', SalaryContribution::class); $validated = $request->validated(); $batch = $this->salaryDeductionService->uploadBatch( (int) $validated['month'], (int) $validated['year'], $validated['details'], $request->user(), ); return response()->json([ 'success' => true, 'data' => new SalaryDeductionBatchResource($batch), 'message' => 'Batch potongan gaji berjaya dimuat naik', ], 201); } public function generate(GenerateSalaryDeductionBatchRequest $request): JsonResponse { $this->authorize('create', SalaryContribution::class); $validated = $request->validated(); $batch = $this->salaryDeductionService->generateBatchFromContributions( (int) $validated['month'], (int) $validated['year'], $request->user(), ); return response()->json([ 'success' => true, 'data' => new SalaryDeductionBatchResource($batch), 'message' => 'Batch potongan gaji berjaya dijana daripada caruman aktif', ], 201); } public function markUnderReview(string $id): JsonResponse { $this->authorize('verify', SalaryContribution::class); $batch = SalaryDeductionBatch::query()->findOrFail($id); $batch = $this->salaryDeductionService->markUnderReview($batch); return response()->json([ 'success' => true, 'data' => new SalaryDeductionBatchResource($batch), 'message' => 'Batch dihantar untuk semakan', ]); } public function verifyDetail( VerifySalaryDeductionDetailRequest $request, string $id, string $detailId, ): JsonResponse { $this->authorize('verify', SalaryContribution::class); $detail = SalaryDeductionBatchDetail::query() ->where('batch_id', $id) ->whereKey($detailId) ->firstOrFail(); $detail = $this->salaryDeductionService->verifyDetail( $detail, $request->user(), $request->validated('remarks'), ); return response()->json([ 'success' => true, 'data' => new SalaryDeductionBatchDetailResource($detail), 'message' => 'Rekod potongan gaji berjaya disahkan', ]); } public function rejectDetail( RejectSalaryDeductionRequest $request, string $id, string $detailId, ): JsonResponse { $this->authorize('verify', SalaryContribution::class); $detail = SalaryDeductionBatchDetail::query() ->where('batch_id', $id) ->whereKey($detailId) ->firstOrFail(); $detail = $this->salaryDeductionService->rejectDetail( $detail, $request->user(), $request->validated('remarks'), ); return response()->json([ 'success' => true, 'data' => new SalaryDeductionBatchDetailResource($detail), 'message' => 'Rekod potongan gaji berjaya ditolak', ]); } public function verifyAll(string $id): JsonResponse { $this->authorize('verify', SalaryContribution::class); $batch = SalaryDeductionBatch::query()->findOrFail($id); $batch = $this->salaryDeductionService->verifyAllPending($batch, request()->user()); return response()->json([ 'success' => true, 'data' => new SalaryDeductionBatchResource($batch), 'message' => 'Semua rekod pending berjaya disahkan', ]); } public function rejectBatch(RejectSalaryDeductionRequest $request, string $id): JsonResponse { $this->authorize('verify', SalaryContribution::class); $batch = SalaryDeductionBatch::query()->findOrFail($id); $batch = $this->salaryDeductionService->rejectBatch( $batch, $request->user(), $request->validated('remarks'), ); return response()->json([ 'success' => true, 'data' => new SalaryDeductionBatchResource($batch), 'message' => 'Batch potongan gaji berjaya ditolak', ]); } }