Improve public controls and dashboard student statistics

This commit is contained in:
2026-05-11 14:51:30 +07:00
parent d695043f37
commit e5b47a3626
7 changed files with 278 additions and 126 deletions
+118
View File
@@ -262,6 +262,124 @@ class StudentPromotionTest extends TestCase
$this->assertDatabaseCount('student_academic_histories', 2);
}
public function test_non_active_students_are_hidden_from_promotion_index_and_rejected_if_posted(): void
{
$admin = User::factory()->create(['role' => 'admin']);
[$fromYear, $toYear, $department, $fromClass, $targetClass] = $this->createPromotionContext();
$droppedStudent = Student::create([
'student_number' => 'S-004',
'full_name' => 'Eko Keluar',
'gender' => 'L',
'academic_year_id' => $fromYear->id,
'department_id' => $department->id,
'class_id' => $fromClass->id,
'status' => 'dropped',
]);
$transferredStudent = Student::create([
'student_number' => 'S-005',
'full_name' => 'Fani Pindah',
'gender' => 'P',
'academic_year_id' => $fromYear->id,
'department_id' => $department->id,
'class_id' => $fromClass->id,
'status' => 'transferred',
]);
$activeStudent = Student::create([
'student_number' => 'S-006',
'full_name' => 'Gilang Aktif',
'gender' => 'L',
'academic_year_id' => $fromYear->id,
'department_id' => $department->id,
'class_id' => $fromClass->id,
'status' => 'active',
]);
$response = $this->actingAs($admin)->get(route('student-promotions.index', [
'from_academic_year_id' => $fromYear->id,
'to_academic_year_id' => $toYear->id,
'class_id' => $fromClass->id,
]));
$response->assertOk();
$response->assertSee('Gilang Aktif');
$response->assertDontSee('Eko Keluar');
$response->assertDontSee('Fani Pindah');
$droppedPost = $this->from(route('student-promotions.index', [
'from_academic_year_id' => $fromYear->id,
'to_academic_year_id' => $toYear->id,
'class_id' => $fromClass->id,
]))->actingAs($admin)->post(route('student-promotions.store'), [
'from_academic_year_id' => $fromYear->id,
'to_academic_year_id' => $toYear->id,
'class_id' => $fromClass->id,
'promotions' => [
[
'student_id' => $droppedStudent->id,
'target_class_id' => $targetClass->id,
'action' => 'promote',
'notes' => 'Tidak boleh ikut promosi.',
],
],
]);
$droppedPost->assertRedirect(route('student-promotions.index', [
'from_academic_year_id' => $fromYear->id,
'to_academic_year_id' => $toYear->id,
'class_id' => $fromClass->id,
]));
$droppedPost->assertSessionHasErrors([
'promotions.0.student_id' => 'Siswa Eko Keluar tidak berstatus aktif sehingga tidak bisa diproses promosi.',
]);
$transferredPost = $this->from(route('student-promotions.index', [
'from_academic_year_id' => $fromYear->id,
'to_academic_year_id' => $toYear->id,
'class_id' => $fromClass->id,
]))->actingAs($admin)->post(route('student-promotions.store'), [
'from_academic_year_id' => $fromYear->id,
'to_academic_year_id' => $toYear->id,
'class_id' => $fromClass->id,
'promotions' => [
[
'student_id' => $transferredStudent->id,
'target_class_id' => $targetClass->id,
'action' => 'promote',
'notes' => 'Tidak boleh ikut promosi.',
],
],
]);
$transferredPost->assertRedirect(route('student-promotions.index', [
'from_academic_year_id' => $fromYear->id,
'to_academic_year_id' => $toYear->id,
'class_id' => $fromClass->id,
]));
$transferredPost->assertSessionHasErrors([
'promotions.0.student_id' => 'Siswa Fani Pindah tidak berstatus aktif sehingga tidak bisa diproses promosi.',
]);
$droppedStudent->refresh();
$transferredStudent->refresh();
$activeStudent->refresh();
$this->assertSame('dropped', $droppedStudent->status);
$this->assertSame('transferred', $transferredStudent->status);
$this->assertSame('active', $activeStudent->status);
$this->assertDatabaseMissing('student_academic_histories', [
'student_id' => $droppedStudent->id,
'academic_year_id' => $toYear->id,
]);
$this->assertDatabaseMissing('student_academic_histories', [
'student_id' => $transferredStudent->id,
'academic_year_id' => $toYear->id,
]);
}
protected function createPromotionContext(array $overrides = []): array
{
$fromYear = AcademicYear::create([