Files
alrahma_sunday_school_api/app/Services/Administrator/AdministratorEnrollmentStatusService.php
T
2026-03-09 02:52:13 -04:00

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'] ?? '',
];
}
}