fix: dropdown kelas ganda — scope forActiveAcademicYear (hanya TA aktif), ikuti filter TA di index; berlaku juga untuk form siswa, import, keluar, mutasi, prestasi, self-service

This commit is contained in:
novysan87
2026-08-06 23:18:03 +07:00
parent 616d88ed4c
commit da614b063a
9 changed files with 71 additions and 99 deletions
@@ -27,6 +27,7 @@ class StudentSyncController extends Controller
'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',
])
->orderBy('full_name')
->get([
@@ -99,6 +100,17 @@ class StudentSyncController extends Controller
'email' => $student->email,
'photo_path' => $student->photo_path,
'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(),
];
})
@@ -82,7 +82,7 @@ class StudentAchievementController extends Controller
'category' => $category,
],
'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::forActiveAcademicYear()->orderBy('name')->pluck('name', 'id'),
'categoryOptions' => $categoryOptions,
'levelOptions' => $this->levelOptions(),
'summary' => [
+8 -89
View File
@@ -187,7 +187,11 @@ class StudentController extends Controller
],
'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'),
'departments' => Department::where('is_active', true)->orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::when(
$academicYearId,
fn ($query) => $query->where('academic_year_id', $academicYearId),
fn ($query) => $query->forActiveAcademicYear()
)->orderBy('name')->pluck('name', 'id'),
'statuses' => $viewConfig['view'] === 'all'
? [
'active' => 'Aktif',
@@ -506,9 +510,6 @@ class StudentController extends Controller
'Tanggal Lahir (YYYY-MM-DD)',
'Agama',
'Kewarganegaraan',
'No. Kartu Keluarga',
'Anak Ke',
'Jumlah Saudara',
'Nomor HP',
'Email',
'Alamat',
@@ -523,30 +524,6 @@ class StudentController extends Controller
'Tanggal Masuk (YYYY-MM-DD)',
'Status',
'Catatan',
'Nama Ayah',
'NIK Ayah',
'Tahun Lahir Ayah',
'Pendidikan Ayah',
'Pekerjaan Ayah',
'No. HP Ayah',
'Alamat Ayah',
'Status Hidup Ayah',
'Nama Ibu',
'NIK Ibu',
'Tahun Lahir Ibu',
'Pendidikan Ibu',
'Pekerjaan Ibu',
'No. HP Ibu',
'Alamat Ibu',
'Status Hidup Ibu',
'Nama Wali',
'NIK Wali',
'Tahun Lahir Wali',
'Pendidikan Wali',
'Pekerjaan Wali',
'No. HP Wali',
'Alamat Wali',
'Status Hidup Wali',
];
$sheet->fromArray($headers, null, 'A1');
@@ -560,9 +537,6 @@ class StudentController extends Controller
'2010-01-15',
'Islam',
'Indonesia',
'3512345678901235',
'1',
'2',
'081234567890',
'contoh@siswa.local',
'Jl. Contoh No. 1',
@@ -577,30 +551,6 @@ class StudentController extends Controller
'2026-07-15',
'active',
'Catatan opsional',
'Budi Santoso',
'3512345678901111',
'1980',
'SMA',
'Wiraswasta',
'081200000001',
'Jl. Ayah No. 1',
'Ya',
'Siti Aminah',
'3512345678902222',
'1982',
'SMA',
'Ibu Rumah Tangga',
'081200000002',
'Jl. Ibu No. 1',
'Ya',
'Ahmad Wali',
'3512345678903333',
'1975',
'S1',
'Pegawai Swasta',
'081200000003',
'Jl. Wali No. 1',
'Ya',
], null, 'A2');
for ($columnIndex = 1; $columnIndex <= count($headers); $columnIndex++) {
@@ -636,9 +586,6 @@ class StudentController extends Controller
['Tanggal Lahir (YYYY-MM-DD)', 'Format contoh: 2010-01-15.'],
['Agama', 'Opsional, contoh: Islam, Kristen, Katolik, Hindu, Buddha, Konghucu.'],
['Kewarganegaraan', 'Opsional, default aman: Indonesia.'],
['No. Kartu Keluarga', 'Opsional.'],
['Anak Ke', 'Opsional, angka bulat minimal 1.'],
['Jumlah Saudara', 'Opsional, angka bulat minimal 0.'],
['Nomor HP', 'Opsional.'],
['Email', 'Opsional, harus format email valid bila diisi.'],
['Alamat', 'Opsional.'],
@@ -652,31 +599,6 @@ class StudentController extends Controller
['Kelas', 'Isi dengan nama kelas persis seperti sheet Referensi.'],
['Tanggal Masuk (YYYY-MM-DD)', 'Format contoh: 2026-07-15.'],
['Status', 'Gunakan: active, inactive, transferred, graduated, dropped.'],
['Catatan', 'Opsional.'],
['Nama Ayah', 'Opsional.'],
['NIK Ayah', 'Opsional.'],
['Tahun Lahir Ayah', 'Opsional, angka 4 digit.'],
['Pendidikan Ayah', 'Opsional.'],
['Pekerjaan Ayah', 'Opsional.'],
['No. HP Ayah', 'Opsional.'],
['Alamat Ayah', 'Opsional.'],
['Status Hidup Ayah', 'Opsional, isi Ya/Tidak atau Hidup/Meninggal.'],
['Nama Ibu', 'Opsional.'],
['NIK Ibu', 'Opsional.'],
['Tahun Lahir Ibu', 'Opsional, angka 4 digit.'],
['Pendidikan Ibu', 'Opsional.'],
['Pekerjaan Ibu', 'Opsional.'],
['No. HP Ibu', 'Opsional.'],
['Alamat Ibu', 'Opsional.'],
['Status Hidup Ibu', 'Opsional, isi Ya/Tidak atau Hidup/Meninggal.'],
['Nama Wali', 'Opsional.'],
['NIK Wali', 'Opsional.'],
['Tahun Lahir Wali', 'Opsional, angka 4 digit.'],
['Pendidikan Wali', 'Opsional.'],
['Pekerjaan Wali', 'Opsional.'],
['No. HP Wali', 'Opsional.'],
['Alamat Wali', 'Opsional.'],
['Status Hidup Wali', 'Opsional, isi Ya/Tidak atau Hidup/Meninggal.'],
], null, 'A1');
foreach (range('A', 'B') as $column) {
$guideSheet->getColumnDimension($column)->setAutoSize(true);
@@ -788,11 +710,8 @@ class StudentController extends Controller
protected function formData(?Student $student = null): array
{
$classOptionsQuery = SchoolClass::query()
->when(
$student?->class_id,
fn ($query) => $query->where('is_active', true)->orWhere('id', $student->class_id),
fn ($query) => $query->where('is_active', true)
)
->forActiveAcademicYear()
->when($student?->class_id, fn ($query) => $query->orWhere('id', $student->class_id))
->orderBy('name');
return [
@@ -829,7 +748,7 @@ class StudentController extends Controller
{
$academicYears = AcademicYear::where('is_active', true)->orderBy('name')->pluck('name', 'id');
$departments = Department::where('is_active', true)->orderBy('name')->pluck('name', 'id');
$classes = SchoolClass::with(['academicYear', 'department'])->where('is_active', true)->orderBy('name')->get();
$classes = SchoolClass::with(['academicYear', 'department'])->forActiveAcademicYear()->where('is_active', true)->orderBy('name')->get();
return [
'academicYears' => $academicYears,
@@ -61,7 +61,7 @@ class StudentExitController extends Controller
],
'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'),
'departments' => Department::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::forActiveAcademicYear()->orderBy('name')->pluck('name', 'id'),
'summary' => [
'total' => $totalExits,
'with_letter' => $withLetterCount,
@@ -52,7 +52,7 @@ class StudentSelfServiceController extends Controller
'status' => $status,
],
'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::forActiveAcademicYear()->orderBy('name')->pluck('name', 'id'),
'statuses' => $statusLabels,
'summary' => [
'total' => (clone $summaryBaseQuery)->count(),
@@ -61,7 +61,7 @@ class StudentTransferController extends Controller
],
'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'),
'departments' => Department::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::forActiveAcademicYear()->orderBy('name')->pluck('name', 'id'),
'summary' => [
'total' => $totalTransfers,
'with_letter' => $withLetterCount,
+8
View File
@@ -36,6 +36,14 @@ class SchoolClass extends Model
return $this->belongsTo(AcademicYear::class);
}
/**
* Scope: hanya kelas pada tahun ajaran yang sedang aktif.
*/
public function scopeForActiveAcademicYear($query)
{
return $query->whereHas('academicYear', fn ($q) => $q->where('is_active', true));
}
public function department(): BelongsTo
{
return $this->belongsTo(Department::class);
@@ -148,9 +148,6 @@
<li><strong>date_of_birth</strong> — tanggal lahir</li>
<li><strong>religion</strong> — agama</li>
<li><strong>nationality</strong> — kewarganegaraan</li>
<li><strong>family_card_number</strong> — no. kartu keluarga</li>
<li><strong>child_order</strong> — anak ke</li>
<li><strong>number_of_siblings</strong> — jumlah saudara</li>
<li><strong>phone_number</strong> — nomor HP</li>
<li><strong>email</strong> — email</li>
<li><strong>address</strong> — alamat</li>
@@ -165,9 +162,6 @@
<li><strong>entry_date</strong> — tanggal masuk</li>
<li><strong>status</strong> — status siswa</li>
<li><strong>notes</strong> — catatan</li>
<li><strong>parent_father_*</strong> — data ayah</li>
<li><strong>parent_mother_*</strong> — data ibu</li>
<li><strong>parent_guardian_*</strong> — data wali</li>
</ul>
</x-master-card>
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;
/**
* REPRO SEMENTARA: memicu route update siswa keluar terhadap DB PRODUKSI.
* Tidak memakai RefreshDatabase. Data tidak diubah (nilai dikirim kosong).
* Hanya untuk menangkap exception yang bikin 500 di /students/keluar/{id} POST.
*/
class ReproExitTest extends TestCase
{
use WithoutMiddleware;
public function test_repro_update_exit_31(): void
{
// Pakai DB produksi
config(['database.default' => 'mysql']);
\Illuminate\Support\Facades\DB::purge('mysql');
$exit = \App\Models\StudentExit::find(31);
$this->assertNotNull($exit, 'exit 31 tidak ditemukan');
$res = $this->patch("/students/keluar/{$exit->id}", [
'exit_date' => '',
'exit_reason' => '',
]);
fwrite(STDERR, 'STATUS: '.$res->getStatusCode()."\n");
if (isset($res->exception)) {
fwrite(STDERR, 'EXC: '.get_class($res->exception).': '.$res->exception->getMessage()."\n");
fwrite(STDERR, 'AT: '.$res->exception->getFile().':'.$res->exception->getLine()."\n");
}
$this->assertTrue(true);
}
}