274 lines
8.6 KiB
PHP
274 lines
8.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Administrator;
|
|
|
|
use App\Models\Student;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class AdministratorEnrollmentStatusService
|
|
{
|
|
public function __construct(
|
|
protected AdministratorSharedService $shared,
|
|
protected Student $studentModel,
|
|
protected User $userModel,
|
|
protected AdministratorEnrollmentRefundService $refundService,
|
|
protected AdministratorEnrollmentEventService $eventService,
|
|
) {
|
|
}
|
|
|
|
public function updateStatuses(array $enrollmentStatuses, int $editorUserId): array
|
|
{
|
|
$schoolYear = $this->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'] ?? '',
|
|
];
|
|
}
|
|
}
|