config->getSchoolYear(); $refundDeadline = $this->config->getRefundDeadline(); $weeksOfStudy = $this->config->getWeeksOfStudy(); $schoolEndDate = $this->config->getSchoolEndDate(); $totalPaid = Payment::getTotalPaidByParentId($parentId, $schoolYear); if ($totalPaid <= 0) { return $this->resultPayload(0.0, $totalPaid, $refundDeadline, $schoolEndDate, $weeksOfStudy, 0); } $registered = []; $withdrawn = []; foreach ($students as $student) { $status = strtolower((string) ($student['enrollment_status'] ?? '')); $admission = strtolower((string) ($student['admission_status'] ?? '')); if (in_array($status, ['withdrawn', 'refund pending', 'withdraw under review'], true)) { $withdrawn[] = $student; continue; } if (in_array($status, ['enrolled', 'payment pending'], true) && $admission === 'accepted') { $registered[] = $student; } } if (empty($withdrawn)) { return $this->resultPayload(0.0, $totalPaid, $refundDeadline, $schoolEndDate, $weeksOfStudy, 0); } $allStudents = array_merge($registered, $withdrawn); $allStudents = $this->studentFees->assignFees($allStudents); $feeByStudentId = []; foreach ($allStudents as $student) { $key = $student['student_id'] ?? null; if ($key === null) { continue; } $feeByStudentId[(string) $key] = (float) ($student['tuition_fee'] ?? 0); } $refundAmount = 0.0; $withdrawCount = 0; foreach ($withdrawn as $student) { $withdrawalDate = $student['withdrawal_date'] ?? null; if (!$withdrawalDate) { Log::warning('Missing withdraw date for student', ['student_id' => $student['student_id'] ?? null]); continue; } if (!$refundDeadline || strtotime($withdrawalDate) > strtotime($refundDeadline)) { continue; } if (!$schoolEndDate) { continue; } $withdrawDateObj = new \DateTime(date('Y-m-d', strtotime($withdrawalDate))); $schoolEndDateObj = new \DateTime($schoolEndDate); $daysRemaining = $withdrawDateObj->diff($schoolEndDateObj)->days; $weeksRemaining = min($weeksOfStudy, max(0, (int) ceil($daysRemaining / 7))); $studentId = (string) ($student['student_id'] ?? ''); $studentFee = $feeByStudentId[$studentId] ?? 0.0; if ($studentFee <= 0 || $weeksOfStudy <= 0) { continue; } $proportionalRefund = ($studentFee / $weeksOfStudy) * $weeksRemaining; $refundAmount += $proportionalRefund; $withdrawCount++; } if ($refundAmount > $totalPaid) { $refundAmount = $totalPaid; } return $this->resultPayload($refundAmount, $totalPaid, $refundDeadline, $schoolEndDate, $weeksOfStudy, $withdrawCount); } private function resultPayload( float $refund, float $totalPaid, ?string $refundDeadline, ?string $schoolEndDate, float $weeksOfStudy, int $withdrawCount ): array { return [ 'refund_amount' => round($refund, 2), 'total_paid' => round($totalPaid, 2), 'refund_deadline' => $refundDeadline, 'school_end_date' => $schoolEndDate, 'weeks_of_study' => $weeksOfStudy, 'withdrawn_students' => $withdrawCount, ]; } }