Files
alrahma_sunday_school/app/Commands/EnrollmentDataAuditCommand.php
T
root 608aca79b8
Deploy to Shared Hosting / Shared hosting deploy (push) Failing after 47s
Tests / PHPUnit (push) Failing after 1m19s
fix enrollment, invoice, payment and financila aid
2026-08-24 21:20:58 -04:00

156 lines
6.0 KiB
PHP

<?php
namespace App\Commands;
use App\Support\Enrollment\DeliberationDecision;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use CodeIgniter\Database\BaseConnection;
class EnrollmentDataAuditCommand extends BaseCommand
{
protected $group = 'Registration';
protected $name = 'registration:enrollment-data-audit';
protected $description = 'Audit withdrawn terminology normalization and duplicate enrollment rows per student/year.';
protected $usage = 'php spark registration:enrollment-data-audit [--school-year=2026-2027] [--json]';
protected $options = [
'--school-year' => 'Optional school year filter for duplicate enrollment detection.',
'--json' => 'Print machine-readable JSON.',
];
private BaseConnection $db;
public function run(array $params)
{
$this->db = \Config\Database::connect();
$schoolYear = trim((string) (CLI::getOption('school-year') ?? ''));
$report = [
'generated_at' => date('Y-m-d H:i:s'),
'school_year_filter' => $schoolYear !== '' ? $schoolYear : null,
'withdrawn_normalization' => $this->auditWithdrawnValues(),
'duplicate_enrollments' => $this->auditDuplicateEnrollments($schoolYear),
];
if (CLI::getOption('json') !== null) {
CLI::write(json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
return;
}
CLI::write('Enrollment Data Audit', 'green');
CLI::newLine();
CLI::write('Withdrawn / misspelling findings: ' . count($report['withdrawn_normalization']), 'yellow');
foreach ($report['withdrawn_normalization'] as $row) {
CLI::write(sprintf(
' [%s] %s.%s = %s',
$row['table'],
$row['column'],
$row['id'] ?? $row['student_id'] ?? '?',
$row['value']
));
}
CLI::newLine();
CLI::write('Duplicate enrollment groups: ' . count($report['duplicate_enrollments']), 'yellow');
foreach ($report['duplicate_enrollments'] as $group) {
CLI::write(sprintf(
' student=%d year=%s rows=%d ids=[%s]',
$group['student_id'],
$group['school_year'],
$group['row_count'],
implode(',', $group['enrollment_ids'])
));
}
}
/**
* @return list<array<string, mixed>>
*/
private function auditWithdrawnValues(): array
{
$findings = [];
$patterns = ['widthrawan', 'widthrwan', 'withdraw'];
if ($this->db->tableExists('enrollments')) {
$rows = $this->db->table('enrollments')
->select('id, student_id, school_year, enrollment_status')
->get()
->getResultArray();
foreach ($rows as $row) {
$status = strtolower(trim((string) ($row['enrollment_status'] ?? '')));
foreach ($patterns as $pattern) {
if ($status === $pattern || str_contains($status, $pattern)) {
$findings[] = [
'table' => 'enrollments',
'column' => 'enrollment_status',
'id' => (int) ($row['id'] ?? 0),
'student_id' => (int) ($row['student_id'] ?? 0),
'school_year' => (string) ($row['school_year'] ?? ''),
'value' => (string) ($row['enrollment_status'] ?? ''),
'recommended' => 'withdrawn',
];
}
}
}
}
if ($this->db->tableExists('student_decisions')) {
$rows = $this->db->table('student_decisions')
->select('id, student_id, school_year, decision, deliberation_decision_standard')
->get()
->getResultArray();
foreach ($rows as $row) {
foreach (['decision', 'deliberation_decision_standard'] as $column) {
$raw = (string) ($row[$column] ?? '');
$normalized = DeliberationDecision::normalize($raw);
if ($raw !== '' && $normalized === DeliberationDecision::WITHDRAWN && strtoupper($raw) !== DeliberationDecision::WITHDRAWN) {
$findings[] = [
'table' => 'student_decisions',
'column' => $column,
'id' => (int) ($row['id'] ?? 0),
'student_id' => (int) ($row['student_id'] ?? 0),
'school_year' => (string) ($row['school_year'] ?? ''),
'value' => $raw,
'recommended' => DeliberationDecision::WITHDRAWN,
];
}
}
}
}
return $findings;
}
/**
* @return list<array<string, mixed>>
*/
private function auditDuplicateEnrollments(string $schoolYear): array
{
if (! $this->db->tableExists('enrollments')) {
return [];
}
$builder = $this->db->table('enrollments')
->select('student_id, school_year, COUNT(*) AS row_count, GROUP_CONCAT(id ORDER BY updated_at DESC, id DESC) AS enrollment_ids', false)
->groupBy('student_id, school_year')
->having('row_count >', 1);
if ($schoolYear !== '') {
$builder->where('school_year', $schoolYear);
}
$groups = [];
foreach ($builder->get()->getResultArray() as $row) {
$ids = array_values(array_filter(array_map('intval', explode(',', (string) ($row['enrollment_ids'] ?? '')))));
$groups[] = [
'student_id' => (int) ($row['student_id'] ?? 0),
'school_year' => (string) ($row['school_year'] ?? ''),
'row_count' => (int) ($row['row_count'] ?? 0),
'enrollment_ids' => $ids,
];
}
return $groups;
}
}