feat: snapshot class_name di setiap presensi & pelanggaran

Migration: tambah kolom:
- attendances.class_name (varchar 100)
- violations.student_class (varchar 100)
- Backfill data existing dari students.class_name

Controller manual: simpan class_name dari form
Sync E-Jurnal: simpan class_name dari lookup student
ViolationService: ambil class_name dari student saat buat
Model: tambah ke fillable

Ini menjamin data historis tetap akurat meskipun
 siswa naik kelas (X→XI→XII) di tahun ajaran baru.
This commit is contained in:
Bro
2026-07-24 18:38:35 +07:00
parent 30c6927658
commit 4fa709509f
6 changed files with 53 additions and 4 deletions
@@ -51,9 +51,11 @@ class AttendanceSyncController extends Controller
]; ];
$sourceIds = array_unique(array_column($attendances, 'source_student_id')); $sourceIds = array_unique(array_column($attendances, 'source_student_id'));
$studentMap = Student::whereIn('source_id', $sourceIds) \$students = Student::whereIn('source_id', $sourceIds)
->where('is_active', true) ->where('is_active', true)
->pluck('id', 'source_id'); ->get(['id', 'source_id', 'class_name']);
$studentMap = $students->pluck('id', 'source_id');
$classNameMap = $students->pluck('class_name', 'id');
$alphaCounts = []; $alphaCounts = [];
$alphaDate = null; $alphaDate = null;
@@ -88,6 +90,7 @@ class AttendanceSyncController extends Controller
], ],
[ [
'status' => $localStatus, 'status' => $localStatus,
'class_name' => $classNameMap[$localStudentId] ?? null,
'notes' => $item['notes'] ?? null, 'notes' => $item['notes'] ?? null,
'recorded_by' => null, 'recorded_by' => null,
] ]
@@ -162,6 +162,7 @@ class AttendanceController extends Controller
], ],
[ [
'status' => $data['status'], 'status' => $data['status'],
'class_name' => $class_name,
'recorded_by' => $request->user()->id, 'recorded_by' => $request->user()->id,
] ]
); );
+1 -1
View File
@@ -8,7 +8,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Attendance extends Model class Attendance extends Model
{ {
protected $fillable = [ protected $fillable = [
'student_id', 'date', 'lesson_hour', 'student_id', 'class_name', 'date', 'lesson_hour',
'status', 'notes', 'recorded_by', 'status', 'notes', 'recorded_by',
]; ];
+1 -1
View File
@@ -12,7 +12,7 @@ class Violation extends Model
use SoftDeletes; use SoftDeletes;
protected $fillable = [ protected $fillable = [
'student_id', 'violation_type_id', 'recorded_by', 'student_id', 'student_class', 'violation_type_id', 'recorded_by',
'description', 'points', 'sanction', 'location', 'description', 'points', 'sanction', 'location',
'violation_date', 'violation_time', 'violation_date', 'violation_time',
'is_verified', 'verified_by', 'verified_at', 'is_verified', 'verified_by', 'verified_at',
+1
View File
@@ -19,6 +19,7 @@ class ViolationService
$violation = DB::transaction(function () use ($data, $userId) { $violation = DB::transaction(function () use ($data, $userId) {
$violation = Violation::create([ $violation = Violation::create([
'student_id' => $data['student_id'], 'student_id' => $data['student_id'],
'student_class' => \App\Models\Student::where('id', $data['student_id'])->value('class_name'),
'violation_type_id' => $data['violation_type_id'], 'violation_type_id' => $data['violation_type_id'],
'recorded_by' => $userId, 'recorded_by' => $userId,
'description' => $data['description'] ?? null, 'description' => $data['description'] ?? null,
@@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
public function up(): void
{
// Add class_name to attendances
Schema::table('attendances', function (Blueprint $table) {
$table->string('class_name', 100)->nullable()->after('student_id');
});
// Add student_class to violations (can't use 'class' — reserved word)
Schema::table('violations', function (Blueprint $table) {
$table->string('student_class', 100)->nullable()->after('student_id');
});
// Backfill existing records with current student class_name
DB::statement("UPDATE attendances a
JOIN students s ON s.id = a.student_id
SET a.class_name = s.class_name
WHERE a.class_name IS NULL");
DB::statement("UPDATE violations v
JOIN students s ON s.id = v.student_id
SET v.student_class = s.class_name
WHERE v.student_class IS NULL");
}
public function down(): void
{
Schema::table('attendances', function (Blueprint $table) {
$table->dropColumn('class_name');
});
Schema::table('violations', function (Blueprint $table) {
$table->dropColumn('student_class');
});
}
};