fix financial and certificates

This commit is contained in:
root
2026-06-05 01:51:08 -04:00
parent d28d11e2e5
commit ad968eaff7
94 changed files with 9654 additions and 214 deletions
@@ -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;
}
}