78 lines
2.2 KiB
PHP
78 lines
2.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Invoices;
|
|
|
|
use App\Models\ClassSection;
|
|
|
|
class InvoiceTuitionService
|
|
{
|
|
public function __construct(
|
|
private InvoiceGradeService $grades,
|
|
private int $gradeFee,
|
|
private float $firstStudentFee,
|
|
private float $secondStudentFee,
|
|
private float $youthFee,
|
|
private string $timezone
|
|
) {}
|
|
|
|
public function calculateTuitionFee(array $registeredKids, array $withdrawnKids, ?string $refundDeadline): float
|
|
{
|
|
$refundOk = $this->isRefundAllowed($refundDeadline);
|
|
$tuitionStudents = $refundOk ? $registeredKids : array_merge($registeredKids, $withdrawnKids);
|
|
|
|
return $this->calculateTotalTuitionFee($tuitionStudents);
|
|
}
|
|
|
|
public function calculateTotalTuitionFee(array $students): float
|
|
{
|
|
foreach ($students as &$student) {
|
|
$gradeName = ClassSection::getClassSectionNameBySectionId($student['class_section_id'] ?? null) ?? '';
|
|
$student['grade'] = strtoupper(trim($gradeName));
|
|
}
|
|
unset($student);
|
|
|
|
$regularCount = 0;
|
|
$youthCount = 0;
|
|
|
|
foreach ($students as $student) {
|
|
$levelInfo = $this->grades->getGradeLevel($student['grade'] ?? '');
|
|
$level = (int) ($levelInfo['level'] ?? 999);
|
|
|
|
if ($level > $this->gradeFee) {
|
|
$youthCount++;
|
|
} else {
|
|
$regularCount++;
|
|
}
|
|
}
|
|
|
|
$total = 0.0;
|
|
$total += $youthCount * $this->youthFee;
|
|
|
|
if ($regularCount >= 2) {
|
|
$total += $this->firstStudentFee;
|
|
$total += ($regularCount - 1) * $this->secondStudentFee;
|
|
} elseif ($regularCount === 1) {
|
|
$total += $this->firstStudentFee;
|
|
}
|
|
|
|
return $total;
|
|
}
|
|
|
|
private function isRefundAllowed(?string $refundDeadline): bool
|
|
{
|
|
if (! $refundDeadline) {
|
|
return true;
|
|
}
|
|
|
|
try {
|
|
$tz = new \DateTimeZone($this->timezone);
|
|
$today = new \DateTimeImmutable('today', $tz);
|
|
$deadline = new \DateTimeImmutable($refundDeadline, $tz);
|
|
|
|
return $today <= $deadline;
|
|
} catch (\Throwable $e) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|