159 lines
5.3 KiB
PHP
159 lines
5.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\Badges;
|
|
|
|
use App\Models\Student;
|
|
use App\Models\StudentClass;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class BadgeStudentLookupService
|
|
{
|
|
public function __construct(
|
|
protected BadgeTextFormatter $formatter
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Active student roster for the badge picker.
|
|
*
|
|
* @param int[] $selectedStudentIds
|
|
* @return array<int, array<string, mixed>>
|
|
*/
|
|
public function fetchStudentList(?string $schoolYear, array $selectedStudentIds = []): array
|
|
{
|
|
$selectedStudentIds = $this->formatter->normalizeIds($selectedStudentIds);
|
|
|
|
$query = DB::table('students')
|
|
->leftJoin('student_class as sc', function ($join) use ($schoolYear) {
|
|
$join->on('sc.student_id', '=', 'students.id');
|
|
|
|
if (!empty($schoolYear)) {
|
|
$join->where('sc.school_year', '=', $schoolYear);
|
|
}
|
|
})
|
|
->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'sc.class_section_id')
|
|
->select([
|
|
'students.id as student_id',
|
|
'students.firstname',
|
|
'students.lastname',
|
|
'students.registration_grade',
|
|
'students.school_id',
|
|
'students.school_year',
|
|
DB::raw("GROUP_CONCAT(DISTINCT cs.class_section_name ORDER BY cs.class_section_name SEPARATOR ', ') as class_section_name"),
|
|
])
|
|
->where('students.is_active', 1)
|
|
->groupBy(
|
|
'students.id',
|
|
'students.firstname',
|
|
'students.lastname',
|
|
'students.registration_grade',
|
|
'students.school_id',
|
|
'students.school_year'
|
|
)
|
|
->orderBy('students.lastname')
|
|
->orderBy('students.firstname');
|
|
|
|
if (!empty($selectedStudentIds)) {
|
|
$query->whereIn('students.id', $selectedStudentIds);
|
|
} elseif (!empty($schoolYear)) {
|
|
$query->where(function ($q) use ($schoolYear) {
|
|
$q->where('students.school_year', $schoolYear)
|
|
->orWhereNotNull('sc.student_id');
|
|
});
|
|
}
|
|
|
|
$rows = array_map(static fn ($row) => (array) $row, $query->get()->all());
|
|
|
|
$out = [];
|
|
foreach ($rows as $row) {
|
|
$studentId = (int) ($row['student_id'] ?? 0);
|
|
if ($studentId <= 0) {
|
|
continue;
|
|
}
|
|
|
|
$schoolId = trim((string) ($row['school_id'] ?? ''));
|
|
if ($schoolId === '' || !preg_match('/^[A-Za-z0-9_-]+$/', $schoolId)) {
|
|
continue;
|
|
}
|
|
|
|
$out[] = [
|
|
'student_id' => $studentId,
|
|
'firstname' => (string) ($row['firstname'] ?? ''),
|
|
'lastname' => (string) ($row['lastname'] ?? ''),
|
|
'role_name' => 'Student',
|
|
'roles' => 'Student',
|
|
'registration_grade' => (string) ($row['registration_grade'] ?? ''),
|
|
'class_section_name' => $this->formatter->norm((string) ($row['class_section_name'] ?? '')),
|
|
'school_id' => $schoolId,
|
|
'school_year' => (string) ($row['school_year'] ?? $schoolYear ?? ''),
|
|
];
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Load students for badge printing: valid school_id (QR payload), ordered by name.
|
|
*
|
|
* @param int[] $studentIds
|
|
* @return array<int, array{student_id:int, fullname:string, grade:string, academic_year:string, school_id:string}>
|
|
*/
|
|
public function fetchForBadges(array $studentIds, ?string $schoolYear): array
|
|
{
|
|
$studentIds = $this->formatter->normalizeIds($studentIds);
|
|
if ($studentIds === []) {
|
|
return [];
|
|
}
|
|
|
|
$rows = Student::query()
|
|
->whereIn('id', $studentIds)
|
|
->where('is_active', 1)
|
|
->orderBy('lastname')
|
|
->orderBy('firstname')
|
|
->get();
|
|
|
|
$out = [];
|
|
foreach ($rows as $student) {
|
|
$schoolId = trim((string) ($student->school_id ?? ''));
|
|
if ($schoolId === '' || !preg_match('/^[A-Za-z0-9_-]+$/', $schoolId)) {
|
|
continue;
|
|
}
|
|
|
|
$fullname = Student::getFullName($student->toArray());
|
|
$grade = $this->resolveGrade((int) $student->id, (string) ($student->registration_grade ?? ''));
|
|
|
|
$academicYear = $schoolYear ?? (string) ($student->school_year ?? '');
|
|
$academicYear = $this->formatter->norm($academicYear);
|
|
|
|
$out[] = [
|
|
'student_id' => (int) $student->id,
|
|
'fullname' => $fullname !== '' ? $fullname : 'Student',
|
|
'grade' => $grade,
|
|
'academic_year' => $academicYear,
|
|
'school_id' => $schoolId,
|
|
];
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
protected function resolveGrade(int $studentId, string $registrationGrade): string
|
|
{
|
|
$registrationGrade = $this->formatter->norm($registrationGrade);
|
|
if ($registrationGrade !== '') {
|
|
return $registrationGrade;
|
|
}
|
|
|
|
try {
|
|
$g = StudentClass::getStudentGrade($studentId);
|
|
$g = $this->formatter->norm((string) $g);
|
|
|
|
return $g !== '' ? $g : '—';
|
|
} catch (\Throwable) {
|
|
return '—';
|
|
}
|
|
}
|
|
}
|