143 lines
6.3 KiB
PHP
143 lines
6.3 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api\Integration;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Student;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
|
|
class StudentSyncController extends Controller
|
|
{
|
|
public function __invoke(Request $request): JsonResponse
|
|
{
|
|
/** @var \App\Models\SyncToken $token */
|
|
$token = $request->attributes->get('syncToken');
|
|
|
|
abort_unless(collect($token->abilities ?? [])->contains('students'), 403, 'Token tidak memiliki akses ke data siswa.');
|
|
|
|
$classLevel = strtoupper(trim((string) $request->query('class_level', '')));
|
|
|
|
$items = Student::query()
|
|
->where('status', 'active')
|
|
->when(in_array($classLevel, ['X', 'XI', 'XII'], true), function ($query) use ($classLevel) {
|
|
$query->whereHas('classRoom', fn ($classQuery) => $classQuery->where('level', $classLevel));
|
|
})
|
|
->with([
|
|
'academicYear:id,name,start_year,end_year,is_active',
|
|
'department:id,code,name,description,is_active',
|
|
'classRoom:id,academic_year_id,department_id,name,level,is_active',
|
|
'parents:id,student_id,relation_type,name,nik,phone_number,is_alive',
|
|
'documents.documentType',
|
|
])
|
|
->orderBy('full_name')
|
|
->get([
|
|
'id',
|
|
'student_number',
|
|
'nisn',
|
|
'full_name',
|
|
'gender',
|
|
'place_of_birth',
|
|
'date_of_birth',
|
|
'nationality',
|
|
'address',
|
|
'postal_code',
|
|
'academic_year_id',
|
|
'department_id',
|
|
'class_id',
|
|
'entry_date',
|
|
'status',
|
|
'phone_number',
|
|
'email',
|
|
'photo_path',
|
|
'notes',
|
|
'updated_at',
|
|
])
|
|
->map(function (Student $student) {
|
|
$photoDocument = $student->documents
|
|
->filter(function ($document) {
|
|
$code = strtoupper((string) ($document->documentType?->code ?? ''));
|
|
$name = strtolower((string) ($document->documentType?->name ?? ''));
|
|
|
|
return $code === 'PAS_FOTO'
|
|
|| $code === 'PAS FOTO'
|
|
|| str_contains($name, 'pas foto')
|
|
|| str_contains($name, 'pasfoto');
|
|
})
|
|
->sortByDesc('created_at')
|
|
->first();
|
|
|
|
return [
|
|
'id' => $student->id,
|
|
'student_number' => $student->student_number,
|
|
'nisn' => $student->nisn,
|
|
'full_name' => $student->full_name,
|
|
'gender' => $student->gender,
|
|
'place_of_birth' => $student->place_of_birth,
|
|
'date_of_birth' => $student->date_of_birth?->toDateString(),
|
|
'nationality' => $student->nationality,
|
|
'address' => $student->address,
|
|
'postal_code' => $student->postal_code,
|
|
'academic_year_id' => $student->academic_year_id,
|
|
'academic_year_name' => $student->academicYear?->name,
|
|
'academic_year' => $student->academicYear ? [
|
|
'id' => $student->academicYear->id,
|
|
'name' => $student->academicYear->name,
|
|
'start_year' => $student->academicYear->start_year,
|
|
'end_year' => $student->academicYear->end_year,
|
|
'is_active' => (bool) $student->academicYear->is_active,
|
|
] : null,
|
|
'department_id' => $student->department_id,
|
|
'department_code' => $student->department?->code,
|
|
'department_name' => $student->department?->name,
|
|
'department' => $student->department ? [
|
|
'id' => $student->department->id,
|
|
'code' => $student->department->code,
|
|
'name' => $student->department->name,
|
|
'description' => $student->department->description,
|
|
'is_active' => (bool) $student->department->is_active,
|
|
] : null,
|
|
'class_id' => $student->class_id,
|
|
'class_name' => $student->classRoom?->name,
|
|
'class_level' => $student->classRoom?->level,
|
|
'classroom' => $student->classRoom ? [
|
|
'id' => $student->classRoom->id,
|
|
'name' => $student->classRoom->name,
|
|
'level' => $student->classRoom->level,
|
|
'academic_year_id' => $student->classRoom->academic_year_id,
|
|
'department_id' => $student->classRoom->department_id,
|
|
'is_active' => (bool) $student->classRoom->is_active,
|
|
] : null,
|
|
'entry_date' => $student->entry_date?->toDateString(),
|
|
'status' => $student->status,
|
|
'phone_number' => $student->phone_number,
|
|
'email' => $student->email,
|
|
'photo_path' => $student->photo_path,
|
|
'photo_url' => $photoDocument?->file_path ? asset('storage/' . $photoDocument->file_path) : null,
|
|
'notes' => $student->notes,
|
|
'parents' => $student->parents
|
|
->where('is_alive', true)
|
|
->values()
|
|
->map(fn ($p) => [
|
|
'id' => $p->id,
|
|
'relation' => $p->relation_type,
|
|
'name' => $p->name,
|
|
'nik' => $p->nik,
|
|
'phone_number' => $p->phone_number,
|
|
])
|
|
->all(),
|
|
'updated_at' => $student->updated_at?->toISOString(),
|
|
];
|
|
})
|
|
->values();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'source' => 'database-kesiswaan',
|
|
'resource' => 'students',
|
|
'count' => $items->count(),
|
|
'data' => $items,
|
|
]);
|
|
}
|
|
}
|