fix financial and certificates
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Services;
|
||||
|
||||
use App\Models\CertificateRecord;
|
||||
use App\Models\ClassSection;
|
||||
use App\Models\Configuration;
|
||||
use App\Models\Student;
|
||||
use App\Models\StudentClass;
|
||||
use App\Models\StudentDecision;
|
||||
use App\Models\User;
|
||||
use App\Services\Certificates\CertificateAdminService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class CertificateAdminServiceTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
private CertificateAdminService $service;
|
||||
|
||||
private string $schoolYear = '2025-2026';
|
||||
|
||||
private ClassSection $section;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Configuration::query()->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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user