create([ 'config_key' => 'school_year', 'config_value' => $this->schoolYear, ]); $this->section = ClassSection::factory()->create([ 'class_section_id' => 501, 'class_section_name' => 'Grade 5-A', ]); $this->service = app(CertificateAdminService::class); } public function test_dashboard_groups_students_and_uses_saved_decisions_as_source_of_truth(): void { $passStudent = $this->enrollStudent('Amina', 'Pass', 'Female'); $repeatStudent = $this->enrollStudent('Bilal', 'Repeat', 'Male'); $pendingStudent = $this->enrollStudent('Celine', 'Pending', 'Female'); StudentDecision::query()->create([ 'student_id' => $passStudent->id, 'school_year' => $this->schoolYear, 'class_section_name' => $this->section->class_section_name, 'year_score' => 95.50, 'decision' => 'Pass', 'source' => 'manual', ]); StudentDecision::query()->create([ 'student_id' => $repeatStudent->id, 'school_year' => $this->schoolYear, 'class_section_name' => $this->section->class_section_name, 'year_score' => 58.25, 'decision' => 'Repeat Class', 'source' => 'manual', ]); CertificateRecord::query()->create([ 'certificate_number' => 'ARSS-2025-2026-0001', 'verification_token' => 'existingtoken', 'student_id' => $passStudent->id, 'student_name' => 'Amina Pass', 'grade' => 'Grade 5', 'cert_date' => '2026-06-05', 'school_year' => $this->schoolYear, 'class_section_id' => $this->section->class_section_id, 'issued_at' => now(), ]); $payload = $this->service->dashboard($this->schoolYear); $this->assertSame($this->schoolYear, $payload['school_year']); $this->assertCount(1, $payload['grade_groups']); $this->assertSame('Grade 5', $payload['grade_groups'][0]['label']); $this->assertTrue($payload['grade_groups'][0]['has_pass']); $this->assertTrue($payload['grade_groups'][0]['fully_done']); $section = $payload['grade_groups'][0]['sections'][0]; $this->assertSame(3, $section['student_count']); $this->assertSame(1, $section['pass_count']); $this->assertSame(1, $section['cert_count']); $this->assertSame(0, $section['remaining_count']); $students = collect($section['students'])->keyBy('student_id'); $this->assertTrue($students[$passStudent->id]['eligible']); $this->assertSame(['Pass'], $students[$passStudent->id]['decision_labels']); $this->assertSame('ARSS-2025-2026-0001', $students[$passStudent->id]['certificate_number']); $this->assertFalse($students[$repeatStudent->id]['eligible']); $this->assertSame(['Repeat Class'], $students[$repeatStudent->id]['decision_labels']); $this->assertFalse($students[$pendingStudent->id]['eligible']); $this->assertSame('pending', $students[$pendingStudent->id]['decision_state']); } public function test_issue_certificates_reuses_existing_record_and_creates_new_one_for_unissued_pass_students(): void { $admin = User::factory()->create(); $existingStudent = $this->enrollStudent('Adam', 'Existing', 'Male'); $newStudent = $this->enrollStudent('Dina', 'New', 'Female'); foreach ([$existingStudent, $newStudent] as $student) { StudentDecision::query()->create([ 'student_id' => $student->id, 'school_year' => $this->schoolYear, 'class_section_name' => $this->section->class_section_name, 'year_score' => 90.00, 'decision' => 'Pass', 'source' => 'manual', ]); } CertificateRecord::query()->create([ 'certificate_number' => 'ARSS-2025-2026-0001', 'verification_token' => 'persistedtoken', 'student_id' => $existingStudent->id, 'student_name' => 'Adam Existing', 'grade' => 'Grade 5', 'cert_date' => '2026-06-05', 'school_year' => $this->schoolYear, 'class_section_id' => $this->section->class_section_id, 'issued_by' => $admin->id, 'issued_at' => now(), ]); $payload = $this->service->issueCertificates( [$existingStudent->id, $newStudent->id], '06/05/2026', $this->section->class_section_id, $this->schoolYear, $admin->id ); $this->assertSame('06/05/2026', $payload['cert_date_display']); $this->assertCount(2, $payload['students']); $issued = collect($payload['students'])->keyBy('id'); $this->assertSame('ARSS-2025-2026-0001', $issued[$existingStudent->id]['cert_number']); $this->assertNotSame('', $issued[$existingStudent->id]['verify_token']); $this->assertSame('ARSS-2025-2026-0002', $issued[$newStudent->id]['cert_number']); $this->assertNotSame('', $issued[$newStudent->id]['verify_token']); $this->assertSame(2, CertificateRecord::query()->where('school_year', $this->schoolYear)->count()); $newRecord = CertificateRecord::query() ->where('student_id', $newStudent->id) ->where('school_year', $this->schoolYear) ->first(); $this->assertNotNull($newRecord); $this->assertSame('Grade 5', $newRecord->grade); $this->assertSame('2026-06-05', $newRecord->cert_date?->format('Y-m-d')); $this->assertSame($admin->id, $newRecord->issued_by); } public function test_audit_log_returns_year_summary_and_filtered_records(): void { CertificateRecord::query()->create([ 'certificate_number' => 'ARSS-2025-2026-0001', 'verification_token' => 'token-a', 'student_id' => 1, 'student_name' => 'Ali One', 'grade' => 'Grade 5', 'cert_date' => '2026-06-05', 'school_year' => '2025-2026', 'issued_at' => now(), ]); CertificateRecord::query()->create([ 'certificate_number' => 'ARSS-2024-2025-0001', 'verification_token' => 'token-b', 'student_id' => 2, 'student_name' => 'Maya Two', 'grade' => 'Grade 4', 'cert_date' => '2025-06-01', 'school_year' => '2024-2025', 'issued_at' => now()->subDay(), ]); $payload = $this->service->auditLog('2025-2026'); $this->assertSame('2025-2026', $payload['school_year']); $this->assertCount(1, $payload['records']); $this->assertSame('ARSS-2025-2026-0001', $payload['records'][0]['certificate_number']); $this->assertCount(2, $payload['year_summary']); } private function enrollStudent(string $firstname, string $lastname, string $gender): Student { $student = Student::factory()->create([ 'firstname' => $firstname, 'lastname' => $lastname, 'gender' => $gender, 'school_year' => $this->schoolYear, 'is_active' => 1, ]); StudentClass::query()->create([ 'student_id' => $student->id, 'class_section_id' => $this->section->class_section_id, 'school_year' => $this->schoolYear, 'semester' => 'Spring', 'is_event_only' => 0, ]); return $student; } }