229 lines
8.3 KiB
PHP
229 lines
8.3 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Parents;
|
|
|
|
use App\Models\EmergencyContact;
|
|
use App\Models\Student;
|
|
use App\Models\StudentAllergy;
|
|
use App\Models\StudentMedicalCondition;
|
|
use App\Models\User;
|
|
use App\Services\SchoolIdService;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class ParentRegistrationService
|
|
{
|
|
public function __construct(
|
|
private ParentConfigService $configService,
|
|
private SchoolIdService $schoolIdService
|
|
) {
|
|
}
|
|
|
|
public function overview(int $parentId): array
|
|
{
|
|
$context = $this->configService->context();
|
|
$parent = User::query()->find($parentId);
|
|
|
|
$kids = Student::query()->where('parent_id', $parentId)->get();
|
|
$kidIds = $kids->pluck('id')->all();
|
|
|
|
$allergies = StudentAllergy::query()
|
|
->whereIn('student_id', $kidIds)
|
|
->get()
|
|
->groupBy('student_id');
|
|
|
|
$conditions = StudentMedicalCondition::query()
|
|
->whereIn('student_id', $kidIds)
|
|
->get()
|
|
->groupBy('student_id');
|
|
|
|
$kids = $kids->map(function ($kid) use ($allergies, $conditions) {
|
|
$kid->allergies = ($allergies[$kid->id] ?? collect())->pluck('allergy')->all();
|
|
$kid->medical_conditions = ($conditions[$kid->id] ?? collect())->pluck('condition_name')->all();
|
|
return $kid->toArray();
|
|
})->all();
|
|
|
|
$emergencies = EmergencyContact::query()->where('parent_id', $parentId)->get()->toArray();
|
|
|
|
return [
|
|
'parent' => $parent ? $parent->toArray() : null,
|
|
'existingKids' => $kids,
|
|
'emergencies' => $emergencies,
|
|
'maxChilds' => $context['max_kids'],
|
|
'maxEmergency' => $context['max_emergency'],
|
|
'lastDayOfRegistration' => $context['enrollment_deadline'],
|
|
'registrationAgeDeadline' => $context['date_age_reference'],
|
|
];
|
|
}
|
|
|
|
public function register(int $parentId, array $students, array $emergencyContacts): array
|
|
{
|
|
$context = $this->configService->context();
|
|
$schoolYear = $context['school_year'];
|
|
$semester = $context['semester'];
|
|
$ageReference = $context['date_age_reference'] ?: now()->toDateString();
|
|
|
|
$existingKidsCount = Student::query()->where('parent_id', $parentId)->count();
|
|
$existingECCount = EmergencyContact::query()->where('parent_id', $parentId)->count();
|
|
|
|
if ($existingKidsCount + count($students) > $context['max_kids']) {
|
|
throw new \RuntimeException('Student limit exceeded.');
|
|
}
|
|
|
|
if ($existingECCount + count($emergencyContacts) > $context['max_emergency']) {
|
|
throw new \RuntimeException('Emergency contact limit exceeded.');
|
|
}
|
|
|
|
$createdStudentIds = [];
|
|
|
|
DB::transaction(function () use (
|
|
$parentId,
|
|
$students,
|
|
$emergencyContacts,
|
|
$schoolYear,
|
|
$semester,
|
|
&$createdStudentIds
|
|
) {
|
|
foreach ($students as $student) {
|
|
$exists = Student::query()
|
|
->where('school_year', $schoolYear)
|
|
->where('dob', $student['dob'])
|
|
->where('firstname', $student['firstname'])
|
|
->where('lastname', $student['lastname'])
|
|
->first();
|
|
|
|
if ($exists) {
|
|
continue;
|
|
}
|
|
|
|
$row = Student::query()->create([
|
|
'firstname' => $student['firstname'],
|
|
'lastname' => $student['lastname'],
|
|
'dob' => $student['dob'],
|
|
'age' => $this->calculateAge($student['dob'], $ageReference),
|
|
'gender' => $student['gender'],
|
|
'registration_grade' => $student['registration_grade'] ?? null,
|
|
'photo_consent' => !empty($student['photo_consent']) ? 1 : 0,
|
|
'parent_id' => $parentId,
|
|
'year_of_registration' => (string) date('Y'),
|
|
'school_year' => $schoolYear,
|
|
'semester' => $semester,
|
|
'is_new' => isset($student['is_new']) ? (int) (bool) $student['is_new'] : null,
|
|
'registration_date' => now(),
|
|
'tuition_paid' => 0,
|
|
'school_id' => $this->schoolIdService->generateStudentSchoolId(),
|
|
]);
|
|
|
|
$createdStudentIds[] = (int) $row->id;
|
|
|
|
foreach (($student['medical_conditions'] ?? []) as $condition) {
|
|
$condition = trim((string) $condition);
|
|
if ($condition === '') {
|
|
continue;
|
|
}
|
|
StudentMedicalCondition::query()->create([
|
|
'student_id' => $row->id,
|
|
'condition_name' => $condition,
|
|
]);
|
|
}
|
|
|
|
foreach (($student['allergies'] ?? []) as $allergy) {
|
|
$allergy = trim((string) $allergy);
|
|
if ($allergy === '') {
|
|
continue;
|
|
}
|
|
StudentAllergy::query()->create([
|
|
'student_id' => $row->id,
|
|
'allergy' => $allergy,
|
|
]);
|
|
}
|
|
}
|
|
|
|
foreach ($emergencyContacts as $contact) {
|
|
EmergencyContact::query()->create([
|
|
'parent_id' => $parentId,
|
|
'emergency_contact_name' => $contact['name'],
|
|
'cellphone' => $contact['cellphone'],
|
|
'email' => $contact['email'] ?? null,
|
|
'relation' => $contact['relation'] ?? null,
|
|
'semester' => $semester,
|
|
'school_year' => $schoolYear,
|
|
]);
|
|
}
|
|
});
|
|
|
|
return [
|
|
'created_student_ids' => $createdStudentIds,
|
|
];
|
|
}
|
|
|
|
public function updateStudent(int $parentId, int $studentId, array $payload): void
|
|
{
|
|
$student = Student::query()
|
|
->where('id', $studentId)
|
|
->where('parent_id', $parentId)
|
|
->firstOrFail();
|
|
|
|
$ageReference = $this->configService->context()['date_age_reference'] ?: now()->toDateString();
|
|
|
|
$student->update([
|
|
'firstname' => $payload['firstname'],
|
|
'lastname' => $payload['lastname'],
|
|
'dob' => $payload['dob'],
|
|
'age' => $this->calculateAge($payload['dob'], $ageReference),
|
|
'gender' => $payload['gender'],
|
|
'registration_grade' => $payload['registration_grade'] ?? null,
|
|
'photo_consent' => !empty($payload['photo_consent']) ? 1 : 0,
|
|
]);
|
|
|
|
StudentMedicalCondition::query()->where('student_id', $studentId)->delete();
|
|
foreach (($payload['medical_conditions'] ?? []) as $condition) {
|
|
$condition = trim((string) $condition);
|
|
if ($condition === '') {
|
|
continue;
|
|
}
|
|
StudentMedicalCondition::query()->create([
|
|
'student_id' => $studentId,
|
|
'condition_name' => $condition,
|
|
]);
|
|
}
|
|
|
|
StudentAllergy::query()->where('student_id', $studentId)->delete();
|
|
foreach (($payload['allergies'] ?? []) as $allergy) {
|
|
$allergy = trim((string) $allergy);
|
|
if ($allergy === '') {
|
|
continue;
|
|
}
|
|
StudentAllergy::query()->create([
|
|
'student_id' => $studentId,
|
|
'allergy' => $allergy,
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function deleteStudent(int $parentId, int $studentId): void
|
|
{
|
|
$student = Student::query()
|
|
->where('id', $studentId)
|
|
->where('parent_id', $parentId)
|
|
->firstOrFail();
|
|
|
|
$student->delete();
|
|
|
|
$remaining = Student::query()->where('parent_id', $parentId)->count();
|
|
if ($remaining === 0) {
|
|
EmergencyContact::query()->where('parent_id', $parentId)->delete();
|
|
}
|
|
}
|
|
|
|
private function calculateAge(string $dob, string $referenceDate): int
|
|
{
|
|
try {
|
|
$dobObj = new \DateTimeImmutable($dob);
|
|
$refObj = new \DateTimeImmutable($referenceDate);
|
|
return (int) $dobObj->diff($refObj)->y;
|
|
} catch (\Throwable $e) {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|