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; } } }