shared->getSchoolYear(); $semester = $this->shared->getSemester(); try { if (empty($enrollmentStatuses)) { return [ 'success' => false, 'message' => 'No enrollment statuses were submitted.', 'status' => 422, ]; } DB::beginTransaction(); $errors = []; $groupsByParentStatus = []; $parentInfo = []; $refundParents = []; $validStatuses = [ 'admission under review', 'payment pending', 'enrolled', 'withdraw under review', 'refund pending', 'withdrawn', 'denied', 'waitlist', ]; foreach ($enrollmentStatuses as $studentId => $newEnrollmentStatus) { $studentId = (int) $studentId; if (!in_array($newEnrollmentStatus, $validStatuses, true)) { $errors[] = "Invalid enrollment status '{$newEnrollmentStatus}' for student ID {$studentId}."; continue; } $result = $this->upsertSingleStatus( $studentId, $newEnrollmentStatus, $schoolYear, $semester, $parentInfo, $groupsByParentStatus, $refundParents ); if (!$result['success']) { $errors[] = $result['message']; } } $refundResult = $this->refundService->processRefunds( array_keys($refundParents), $schoolYear, $editorUserId ); $errors = array_merge($errors, $refundResult['errors']); DB::commit(); $this->eventService->dispatchGroupedEvents( $groupsByParentStatus, $parentInfo, $refundResult['refundAmountByParent'], $schoolYear ); return [ 'success' => empty($errors), 'message' => empty($errors) ? 'Enrollment statuses updated and notifications sent.' : implode(' ', $errors), 'status' => empty($errors) ? 200 : 207, ]; } catch (\Throwable $e) { DB::rollBack(); Log::error('Enrollment withdrawal error: ' . $e->getMessage()); return [ 'success' => false, 'message' => 'An unexpected error occurred while processing enrollments.', 'status' => 500, ]; } } protected function upsertSingleStatus( int $studentId, string $newEnrollmentStatus, string $schoolYear, string $semester, array &$parentInfo, array &$groupsByParentStatus, array &$refundParents ): array { $admissionStatus = match ($newEnrollmentStatus) { 'denied' => 'denied', 'enrolled', 'payment pending' => 'accepted', default => 'pending', }; $enrollmentRow = DB::table('enrollments') ->where('student_id', $studentId) ->where('school_year', $schoolYear) ->first(); if (!$enrollmentRow) { return $this->createEnrollmentRow( $studentId, $newEnrollmentStatus, $admissionStatus, $schoolYear, $semester, $parentInfo, $groupsByParentStatus, $refundParents ); } $oldStatus = $enrollmentRow->enrollment_status ?? null; $parentId = (int) ($enrollmentRow->parent_id ?? 0); if (!$parentId) { return [ 'success' => false, 'message' => "No parent ID found for student ID {$studentId}.", ]; } if ($oldStatus === $newEnrollmentStatus) { return ['success' => true, 'message' => 'No change']; } $updated = DB::table('enrollments') ->where('student_id', $studentId) ->where('school_year', $schoolYear) ->update([ 'enrollment_status' => $newEnrollmentStatus, 'admission_status' => $admissionStatus, 'updated_at' => now(), ]); if (!$updated) { return [ 'success' => false, 'message' => "Failed to update enrollment for student ID {$studentId}.", ]; } $studentName = $this->resolveStudentName($studentId); $this->ensureParentInfoLoaded($parentId, $parentInfo); $groupsByParentStatus[$parentId][$newEnrollmentStatus][] = [ 'student_id' => $studentId, 'student_name' => $studentName, ]; if ($newEnrollmentStatus === 'refund pending') { $refundParents[$parentId] = true; } return ['success' => true, 'message' => 'Updated']; } protected function createEnrollmentRow( int $studentId, string $newEnrollmentStatus, string $admissionStatus, string $schoolYear, string $semester, array &$parentInfo, array &$groupsByParentStatus, array &$refundParents ): array { $stu = $this->studentModel->find($studentId); $stu = is_array($stu) ? $stu : ($stu?->toArray() ?? []); $parentId = (int) ($stu['parent_id'] ?? ($stu['secondparent_user_id'] ?? 0)); if (!$parentId) { return [ 'success' => false, 'message' => "No parent ID found for student ID {$studentId}.", ]; } $isWithdrawn = in_array($newEnrollmentStatus, ['withdrawn', 'refund pending', 'withdraw under review'], true) ? 1 : 0; $ok = DB::table('enrollments')->insert([ 'student_id' => $studentId, 'parent_id' => $parentId, 'school_year' => $schoolYear, 'semester' => $semester, 'enrollment_date' => now()->toDateString(), 'is_withdrawn' => $isWithdrawn, 'enrollment_status' => $newEnrollmentStatus, 'admission_status' => $admissionStatus, 'created_at' => now(), 'updated_at' => now(), ]); if (!$ok) { return [ 'success' => false, 'message' => "Failed to create enrollment for student ID {$studentId}.", ]; } $studentName = $this->resolveStudentName($studentId); $this->ensureParentInfoLoaded($parentId, $parentInfo); $groupsByParentStatus[$parentId][$newEnrollmentStatus][] = [ 'student_id' => $studentId, 'student_name' => $studentName, ]; if ($newEnrollmentStatus === 'refund pending') { $refundParents[$parentId] = true; } return ['success' => true, 'message' => 'Created']; } protected function resolveStudentName(int $studentId): string { $studentRow = $this->studentModel->find($studentId); $studentData = is_array($studentRow) ? $studentRow : ($studentRow?->toArray() ?? []); return trim(($studentData['firstname'] ?? '') . ' ' . ($studentData['lastname'] ?? '')) ?: "Student #{$studentId}"; } protected function ensureParentInfoLoaded(int $parentId, array &$parentInfo): void { if (isset($parentInfo[$parentId])) { return; } $p = $this->userModel->find($parentId); $parentData = is_array($p) ? $p : ($p?->toArray() ?? []); $parentInfo[$parentId] = [ 'user_id' => $parentData['id'] ?? $parentId, 'email' => $parentData['email'] ?? null, 'firstname' => $parentData['firstname'] ?? '', 'lastname' => $parentData['lastname'] ?? '', ]; } }