76 lines
2.9 KiB
PHP
76 lines
2.9 KiB
PHP
<?php
|
|
|
|
namespace App\Libraries\Tuition;
|
|
|
|
use App\Interfaces\TuitionCalculatorInterface;
|
|
|
|
final class NewTuitionCalculatorService implements TuitionCalculatorInterface
|
|
{
|
|
public function calculateFamilyTuition(array $students, array $config): array
|
|
{
|
|
$gradeFee = (int) ($config['grade_fee'] ?? 9);
|
|
$fullAmountCents = $this->toCents($config['new_tuition_full_amount'] ?? 370);
|
|
$secondDiscountCents = $this->toCents($config['new_tuition_second_student_discount'] ?? 50);
|
|
$thirdDiscountCents = $this->toCents($config['new_tuition_third_student_discount'] ?? 50);
|
|
$fourthPlusDiscountCents = $this->toCents($config['new_tuition_fourth_plus_discount'] ?? 100);
|
|
|
|
usort($students, function (array $left, array $right) use ($gradeFee): int {
|
|
$leftLevel = GradeLevelParser::parse($left['grade_level'] ?? null, $gradeFee);
|
|
$rightLevel = GradeLevelParser::parse($right['grade_level'] ?? null, $gradeFee);
|
|
|
|
return [$leftLevel, (int) ($left['student_id'] ?? 0)] <=> [$rightLevel, (int) ($right['student_id'] ?? 0)];
|
|
});
|
|
|
|
$details = [];
|
|
|
|
foreach (array_values($students) as $index => $student) {
|
|
$position = $index + 1;
|
|
|
|
if ($position === 1) {
|
|
$discountCents = 0;
|
|
$rule = 'new_first_student_full_amount';
|
|
} elseif ($position === 2) {
|
|
$discountCents = $secondDiscountCents;
|
|
$rule = 'new_second_student_discount';
|
|
} elseif ($position === 3) {
|
|
$discountCents = $thirdDiscountCents;
|
|
$rule = 'new_third_student_discount';
|
|
} else {
|
|
$discountCents = $fourthPlusDiscountCents;
|
|
$rule = 'new_fourth_plus_student_discount';
|
|
}
|
|
|
|
$amountCents = max(0, $fullAmountCents - $discountCents);
|
|
|
|
$details[] = [
|
|
'student_id' => (int) ($student['student_id'] ?? 0),
|
|
'student_name' => (string) ($student['student_name'] ?? ''),
|
|
'grade_level' => $student['grade_level'] ?? null,
|
|
'family_position' => $position,
|
|
'full_amount' => $this->fromCents($fullAmountCents),
|
|
'discount' => $this->fromCents($discountCents),
|
|
'rule' => $rule,
|
|
'amount' => $this->fromCents($amountCents),
|
|
];
|
|
}
|
|
|
|
$total = array_sum(array_map(fn (array $detail): int => $this->toCents($detail['amount']), $details));
|
|
|
|
return [
|
|
'calculator' => 'new',
|
|
'total' => $this->fromCents($total),
|
|
'details' => $details,
|
|
];
|
|
}
|
|
|
|
private function toCents($amount): int
|
|
{
|
|
return (int) round(((float) $amount) * 100);
|
|
}
|
|
|
|
private function fromCents(int $cents): string
|
|
{
|
|
return number_format($cents / 100, 2, '.', '');
|
|
}
|
|
}
|