find($studentId); if (!$student) { return ['ok' => false, 'message' => 'Student not found.']; } $studentData = array_filter([ 'school_id' => $payload['school_id'] ?? null, 'firstname' => $payload['firstname'] ?? null, 'lastname' => $payload['lastname'] ?? null, 'dob' => $payload['dob'] ?? null, 'age' => $payload['age'] ?? null, 'gender' => $payload['gender'] ?? null, 'registration_grade' => $payload['registration_grade'] ?? null, 'photo_consent' => $payload['photo_consent'] ?? null, 'parent_id' => $payload['parent_id'] ?? null, 'registration_date' => $payload['registration_date'] ?? null, 'tuition_paid' => $payload['tuition_paid'] ?? null, 'year_of_registration' => $payload['year_of_registration'] ?? null, 'school_year' => $payload['school_year'] ?? null, 'rfid_tag' => $payload['rfid_tag'] ?? null, 'semester' => $payload['semester'] ?? null, 'is_new' => $payload['is_new'] ?? null, 'is_active' => $payload['is_active'] ?? null, ], static fn ($value) => $value !== null); $conditionsInput = (string) ($payload['medical_conditions'] ?? ''); $allergiesInput = (string) ($payload['allergies'] ?? ''); $conditions = $this->normalizeHealthList($conditionsInput); $allergies = $this->normalizeHealthList($allergiesInput); $shouldSyncConditions = array_key_exists('medical_conditions', $payload); $shouldSyncAllergies = array_key_exists('allergies', $payload); DB::transaction(function () use ($student, $studentData, $conditions, $allergies): void { if (!empty($studentData)) { $student->update($studentData); } if ($shouldSyncConditions) { $this->syncHealthList($student->id, StudentMedicalCondition::class, 'condition_name', $conditions); } if ($shouldSyncAllergies) { $this->syncHealthList($student->id, StudentAllergy::class, 'allergy', $allergies); } }); return ['ok' => true, 'message' => 'Student updated successfully.']; } private function normalizeHealthList(string $value, int $maxLen = 100): array { $value = trim($value); if ($value === '') { return []; } $parts = preg_split('/[,\n;]+/u', $value, -1, PREG_SPLIT_NO_EMPTY) ?: []; $out = []; foreach ($parts as $part) { $item = trim(preg_replace('/\s+/u', ' ', $part)); if ($item === '') { continue; } if (preg_match('/^(none|n\/a|na|null|nil|no)$/i', $item)) { continue; } $out[mb_strtolower($item, 'UTF-8')] = mb_substr($item, 0, $maxLen, 'UTF-8'); } return array_values($out); } private function syncHealthList(int $studentId, string $modelClass, string $field, array $newValues): void { $model = new $modelClass(); $rows = $model->newQuery()->where('student_id', $studentId)->get(['id', $field])->toArray(); $current = []; $byId = []; foreach ($rows as $row) { $val = (string) ($row[$field] ?? ''); $key = mb_strtolower(trim($val), 'UTF-8'); if ($key === '') { continue; } $current[$key] = $val; $byId[$key] = (int) ($row['id'] ?? 0); } $incoming = []; foreach ($newValues as $value) { $key = mb_strtolower(trim($value), 'UTF-8'); if ($key === '') { continue; } $incoming[$key] = $value; } $toDeleteKeys = array_diff(array_keys($current), array_keys($incoming)); $toInsertKeys = array_diff(array_keys($incoming), array_keys($current)); if (!empty($toDeleteKeys)) { $ids = array_map(fn ($key) => $byId[$key], $toDeleteKeys); if (!empty($ids)) { $model->newQuery()->whereIn('id', $ids)->delete(); } } if (!empty($toInsertKeys)) { $batch = []; foreach ($toInsertKeys as $key) { $batch[] = [ 'student_id' => $studentId, $field => $incoming[$key], ]; } if (!empty($batch)) { $model->newQuery()->insert($batch); } } } }