Fix semester context, attendance rosters, and billing workflows
Deploy to Shared Hosting / Shared hosting deploy (push) Failing after 31s
Tests / PHPUnit (push) Failing after 55s

- load global semester helpers consistently and use date-based semester defaults
- fix grading and daily attendance duplicate student/section rows
- keep attendance violations scoped to the current semester by default
- update invoice, refund, discount, payment, and financial aid flows
- add configuration cleanup migrations for duplicate calendar/semester keys
- refresh parent registration/report-card and print request handling
- update related models, services, views, cron notes, and test coverage
This commit is contained in:
root
2026-08-16 17:41:11 -04:00
parent 36c7e3fc6d
commit 0ac3a8375e
99 changed files with 1598 additions and 814 deletions
@@ -0,0 +1,31 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class RemoveDuplicateCalendarConfigurationKeys extends Migration
{
private const DUPLICATE_KEYS = [
'1st_day_of_school',
'Make_up_exam',
'year_start_date',
'registration_day',
];
public function up(): void
{
if (! $this->db->tableExists('configuration')) {
return;
}
$this->db->table('configuration')
->whereIn('config_key', self::DUPLICATE_KEYS)
->delete();
}
public function down(): void
{
// Obsolete duplicate keys should not be recreated.
}
}
@@ -0,0 +1,30 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class RemoveAdditionalDuplicateCalendarConfigurationKeys extends Migration
{
private const DUPLICATE_KEYS = [
'end_of_registration',
'last_school_day',
'year_end_date',
];
public function up(): void
{
if (! $this->db->tableExists('configuration')) {
return;
}
$this->db->table('configuration')
->whereIn('config_key', self::DUPLICATE_KEYS)
->delete();
}
public function down(): void
{
// Obsolete duplicate keys should not be recreated.
}
}
@@ -0,0 +1,59 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AlignFallSemesterStartWithSchoolYearStart extends Migration
{
public function up(): void
{
if (! $this->db->tableExists('configuration')) {
return;
}
$schoolYearStart = $this->configValue('school_year_start_date');
if ($schoolYearStart === null || $schoolYearStart === '') {
return;
}
$this->upsertConfigValue('fall_semester_start', $schoolYearStart);
}
public function down(): void
{
}
private function configValue(string $key): ?string
{
$row = $this->db->table('configuration')
->select('config_value')
->where('config_key', $key)
->orderBy('id', 'DESC')
->get(1)
->getRowArray();
return $row ? (string) $row['config_value'] : null;
}
private function upsertConfigValue(string $key, string $value): void
{
$exists = $this->db->table('configuration')
->select('id')
->where('config_key', $key)
->get(1)
->getRowArray();
if ($exists) {
$this->db->table('configuration')
->where('config_key', $key)
->update(['config_value' => $value]);
return;
}
$this->db->table('configuration')->insert([
'config_key' => $key,
'config_value' => $value,
]);
}
}