add school year model
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if (!Schema::hasTable('school_years')) {
|
||||
Schema::create('school_years', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name', 50)->unique();
|
||||
$table->date('start_date');
|
||||
$table->date('end_date');
|
||||
$table->string('status', 20)->default('draft')->index();
|
||||
$table->boolean('is_current')->default(false)->index();
|
||||
$table->timestamp('closed_at')->nullable();
|
||||
$table->unsignedBigInteger('closed_by')->nullable()->index();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('parent_accounts')) {
|
||||
Schema::create('parent_accounts', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('parent_id')->index();
|
||||
$table->string('school_year', 50)->index();
|
||||
$table->decimal('opening_balance', 12, 2)->default(0);
|
||||
$table->decimal('current_balance', 12, 2)->default(0);
|
||||
$table->timestamps();
|
||||
$table->unique(['parent_id', 'school_year'], 'parent_accounts_parent_year_unique');
|
||||
});
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('parent_balance_transfers')) {
|
||||
Schema::create('parent_balance_transfers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('parent_id')->index();
|
||||
$table->string('from_school_year', 50)->index();
|
||||
$table->string('to_school_year', 50)->index();
|
||||
$table->decimal('amount', 12, 2)->default(0);
|
||||
$table->string('status', 30)->default('pending')->index();
|
||||
$table->json('source_summary_json')->nullable();
|
||||
$table->unsignedBigInteger('new_invoice_id')->nullable()->index();
|
||||
$table->unsignedBigInteger('created_by')->nullable()->index();
|
||||
$table->timestamps();
|
||||
$table->unique(['parent_id', 'from_school_year', 'to_school_year'], 'parent_balance_transfers_parent_year_unique');
|
||||
});
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('audit_logs')) {
|
||||
Schema::create('audit_logs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('user_id')->nullable()->index();
|
||||
$table->string('action', 100)->index();
|
||||
$table->string('table_name', 100)->nullable()->index();
|
||||
$table->unsignedBigInteger('record_id')->nullable()->index();
|
||||
$table->json('old_value')->nullable();
|
||||
$table->json('new_value')->nullable();
|
||||
$table->json('metadata')->nullable();
|
||||
$table->timestamp('created_at')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
if (Schema::hasTable('invoices') && !Schema::hasColumn('invoices', 'balance_transfer_id')) {
|
||||
Schema::table('invoices', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('balance_transfer_id')->nullable()->index()->after('semester');
|
||||
});
|
||||
}
|
||||
|
||||
$this->seedCurrentSchoolYear();
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
if (Schema::hasTable('invoices') && Schema::hasColumn('invoices', 'balance_transfer_id')) {
|
||||
Schema::table('invoices', function (Blueprint $table) {
|
||||
$table->dropColumn('balance_transfer_id');
|
||||
});
|
||||
}
|
||||
|
||||
Schema::dropIfExists('audit_logs');
|
||||
Schema::dropIfExists('parent_balance_transfers');
|
||||
Schema::dropIfExists('parent_accounts');
|
||||
Schema::dropIfExists('school_years');
|
||||
}
|
||||
|
||||
private function seedCurrentSchoolYear(): void
|
||||
{
|
||||
if (!Schema::hasTable('configuration') || !Schema::hasTable('school_years')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current = DB::table('configuration')
|
||||
->where('config_key', 'school_year')
|
||||
->orderByDesc('id')
|
||||
->value('config_value');
|
||||
|
||||
$current = is_string($current) ? trim($current) : '';
|
||||
if ($current === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$exists = DB::table('school_years')->where('name', $current)->exists();
|
||||
if ($exists) {
|
||||
DB::table('school_years')->where('name', $current)->update([
|
||||
'status' => 'active',
|
||||
'is_current' => true,
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
[$startDate, $endDate] = $this->inferDates($current);
|
||||
|
||||
DB::table('school_years')->insert([
|
||||
'name' => $current,
|
||||
'start_date' => $startDate,
|
||||
'end_date' => $endDate,
|
||||
'status' => 'active',
|
||||
'is_current' => true,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
private function inferDates(string $schoolYear): array
|
||||
{
|
||||
if (preg_match('/^(\\d{4})-(\\d{4})$/', $schoolYear, $matches) === 1) {
|
||||
return [
|
||||
sprintf('%s-09-01', $matches[1]),
|
||||
sprintf('%s-06-30', $matches[2]),
|
||||
];
|
||||
}
|
||||
|
||||
$year = (int) date('Y');
|
||||
|
||||
return [
|
||||
sprintf('%d-09-01', $year),
|
||||
sprintf('%d-06-30', $year + 1),
|
||||
];
|
||||
}
|
||||
};
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if (Schema::hasTable('attendance_management_events')) {
|
||||
Schema::table('attendance_management_events', function (Blueprint $table) {
|
||||
if (! Schema::hasColumn('attendance_management_events', 'school_year')) {
|
||||
$table->string('school_year', 20)->nullable()->after('event_date')->index();
|
||||
}
|
||||
if (! Schema::hasColumn('attendance_management_events', 'semester')) {
|
||||
$table->string('semester', 20)->nullable()->after('school_year')->index();
|
||||
}
|
||||
});
|
||||
|
||||
DB::table('attendance_management_events')
|
||||
->select('id', 'event_date', 'school_year', 'semester')
|
||||
->orderBy('id')
|
||||
->chunkById(200, function ($rows): void {
|
||||
foreach ($rows as $row) {
|
||||
$schoolYear = trim((string) ($row->school_year ?? ''));
|
||||
$semester = trim((string) ($row->semester ?? ''));
|
||||
if ($schoolYear !== '' && $semester !== '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$date = CarbonImmutable::parse((string) $row->event_date);
|
||||
DB::table('attendance_management_events')
|
||||
->where('id', $row->id)
|
||||
->update([
|
||||
'school_year' => $schoolYear !== '' ? $schoolYear : $this->deriveSchoolYearForDate($date),
|
||||
'semester' => $semester !== '' ? $semester : $this->deriveSemesterForDate($date),
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (Schema::hasTable('badge_exceptions')) {
|
||||
Schema::table('badge_exceptions', function (Blueprint $table) {
|
||||
if (! Schema::hasColumn('badge_exceptions', 'school_year')) {
|
||||
$table->string('school_year', 20)->nullable()->after('exception_date')->index();
|
||||
}
|
||||
if (! Schema::hasColumn('badge_exceptions', 'semester')) {
|
||||
$table->string('semester', 20)->nullable()->after('school_year')->index();
|
||||
}
|
||||
});
|
||||
|
||||
DB::table('badge_exceptions')
|
||||
->select('id', 'exception_date', 'school_year', 'semester')
|
||||
->orderBy('id')
|
||||
->chunkById(200, function ($rows): void {
|
||||
foreach ($rows as $row) {
|
||||
$schoolYear = trim((string) ($row->school_year ?? ''));
|
||||
$semester = trim((string) ($row->semester ?? ''));
|
||||
if ($schoolYear !== '' && $semester !== '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$date = CarbonImmutable::parse((string) $row->exception_date);
|
||||
DB::table('badge_exceptions')
|
||||
->where('id', $row->id)
|
||||
->update([
|
||||
'school_year' => $schoolYear !== '' ? $schoolYear : $this->deriveSchoolYearForDate($date),
|
||||
'semester' => $semester !== '' ? $semester : $this->deriveSemesterForDate($date),
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (Schema::hasTable('late_slip_reprints')) {
|
||||
Schema::table('late_slip_reprints', function (Blueprint $table) {
|
||||
if (! Schema::hasColumn('late_slip_reprints', 'school_year')) {
|
||||
$table->string('school_year', 20)->nullable()->after('reprinted_at')->index();
|
||||
}
|
||||
if (! Schema::hasColumn('late_slip_reprints', 'semester')) {
|
||||
$table->string('semester', 20)->nullable()->after('school_year')->index();
|
||||
}
|
||||
});
|
||||
|
||||
DB::table('late_slip_reprints')
|
||||
->leftJoin('attendance_management_events as ame', 'ame.id', '=', 'late_slip_reprints.attendance_management_event_id')
|
||||
->select(
|
||||
'late_slip_reprints.id',
|
||||
'late_slip_reprints.reprinted_at',
|
||||
'late_slip_reprints.school_year',
|
||||
'late_slip_reprints.semester',
|
||||
'ame.school_year as event_school_year',
|
||||
'ame.semester as event_semester',
|
||||
)
|
||||
->orderBy('late_slip_reprints.id')
|
||||
->chunkById(200, function ($rows): void {
|
||||
foreach ($rows as $row) {
|
||||
$schoolYear = trim((string) ($row->school_year ?? ''));
|
||||
$semester = trim((string) ($row->semester ?? ''));
|
||||
if ($schoolYear !== '' && $semester !== '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$date = CarbonImmutable::parse((string) $row->reprinted_at);
|
||||
DB::table('late_slip_reprints')
|
||||
->where('id', $row->id)
|
||||
->update([
|
||||
'school_year' => $schoolYear !== '' ? $schoolYear : (trim((string) ($row->event_school_year ?? '')) ?: $this->deriveSchoolYearForDate($date)),
|
||||
'semester' => $semester !== '' ? $semester : (trim((string) ($row->event_semester ?? '')) ?: $this->deriveSemesterForDate($date)),
|
||||
]);
|
||||
}
|
||||
}, 'late_slip_reprints.id', 'id');
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
if (Schema::hasTable('late_slip_reprints')) {
|
||||
Schema::table('late_slip_reprints', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('late_slip_reprints', 'semester')) {
|
||||
$table->dropColumn('semester');
|
||||
}
|
||||
if (Schema::hasColumn('late_slip_reprints', 'school_year')) {
|
||||
$table->dropColumn('school_year');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (Schema::hasTable('badge_exceptions')) {
|
||||
Schema::table('badge_exceptions', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('badge_exceptions', 'semester')) {
|
||||
$table->dropColumn('semester');
|
||||
}
|
||||
if (Schema::hasColumn('badge_exceptions', 'school_year')) {
|
||||
$table->dropColumn('school_year');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (Schema::hasTable('attendance_management_events')) {
|
||||
Schema::table('attendance_management_events', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('attendance_management_events', 'semester')) {
|
||||
$table->dropColumn('semester');
|
||||
}
|
||||
if (Schema::hasColumn('attendance_management_events', 'school_year')) {
|
||||
$table->dropColumn('school_year');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private function deriveSchoolYearForDate(CarbonImmutable $date): string
|
||||
{
|
||||
$startYear = $date->month >= 8 ? $date->year : ($date->year - 1);
|
||||
|
||||
return sprintf('%d-%d', $startYear, $startYear + 1);
|
||||
}
|
||||
|
||||
private function deriveSemesterForDate(CarbonImmutable $date): string
|
||||
{
|
||||
return ($date->month >= 8 || $date->month === 1) ? 'Fall' : 'Spring';
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user