init backend presensi

This commit is contained in:
mwpn
2026-03-05 14:37:36 +07:00
commit b4fda6b9c9
319 changed files with 27261 additions and 0 deletions

View File

View File

@@ -0,0 +1,58 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateDevicesTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'device_code' => [
'type' => 'VARCHAR',
'constraint' => '100',
'unique' => true,
],
'device_name' => [
'type' => 'VARCHAR',
'constraint' => '255',
],
'api_key' => [
'type' => 'VARCHAR',
'constraint' => '255',
],
'is_active' => [
'type' => 'TINYINT',
'constraint' => 1,
'default' => 1,
],
'last_seen_at' => [
'type' => 'DATETIME',
'null' => true,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('devices');
}
public function down()
{
$this->forge->dropTable('devices');
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateClassesTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'name' => [
'type' => 'VARCHAR',
'constraint' => '100',
],
'grade' => [
'type' => 'VARCHAR',
'constraint' => '50',
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('classes');
}
public function down()
{
$this->forge->dropTable('classes');
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateStudentsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'nis' => [
'type' => 'VARCHAR',
'constraint' => '50',
'unique' => true,
],
'name' => [
'type' => 'VARCHAR',
'constraint' => '255',
],
'class_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addKey('class_id');
$this->forge->addForeignKey('class_id', 'classes', 'id', 'CASCADE', 'CASCADE');
$this->forge->createTable('students');
}
public function down()
{
$this->forge->dropTable('students');
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateSubjectsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'name' => [
'type' => 'VARCHAR',
'constraint' => '255',
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('subjects');
}
public function down()
{
$this->forge->dropTable('subjects');
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateSchedulesTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'class_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'subject_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'teacher_name' => [
'type' => 'VARCHAR',
'constraint' => '255',
],
'day_of_week' => [
'type' => 'TINYINT',
'constraint' => 1,
'comment' => '1=Monday, 7=Sunday',
],
'start_time' => [
'type' => 'TIME',
],
'end_time' => [
'type' => 'TIME',
],
'room' => [
'type' => 'VARCHAR',
'constraint' => '100',
'null' => true,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addKey(['class_id', 'day_of_week']);
$this->forge->addForeignKey('class_id', 'classes', 'id', 'CASCADE', 'CASCADE');
$this->forge->addForeignKey('subject_id', 'subjects', 'id', 'CASCADE', 'CASCADE');
$this->forge->createTable('schedules');
}
public function down()
{
$this->forge->dropTable('schedules');
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateZonesTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'zone_code' => [
'type' => 'VARCHAR',
'constraint' => '100',
'unique' => true,
],
'zone_name' => [
'type' => 'VARCHAR',
'constraint' => '255',
],
'latitude' => [
'type' => 'DECIMAL',
'constraint' => '10,8',
],
'longitude' => [
'type' => 'DECIMAL',
'constraint' => '11,8',
],
'radius_meters' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'is_active' => [
'type' => 'TINYINT',
'constraint' => 1,
'default' => 1,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('zones');
}
public function down()
{
$this->forge->dropTable('zones');
}
}

View File

@@ -0,0 +1,78 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateAttendanceSessionsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'student_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'schedule_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'null' => true,
],
'device_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'checkin_at' => [
'type' => 'DATETIME',
],
'latitude' => [
'type' => 'DECIMAL',
'constraint' => '10,8',
],
'longitude' => [
'type' => 'DECIMAL',
'constraint' => '11,8',
],
'confidence' => [
'type' => 'DECIMAL',
'constraint' => '5,2',
'null' => true,
],
'status' => [
'type' => 'ENUM',
'constraint' => ['PRESENT', 'LATE', 'OUTSIDE_ZONE', 'NO_SCHEDULE', 'INVALID_DEVICE'],
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addKey(['student_id', 'checkin_at']);
$this->forge->addKey('schedule_id');
$this->forge->addKey('device_id');
$this->forge->addForeignKey('student_id', 'students', 'id', 'CASCADE', 'CASCADE');
$this->forge->addForeignKey('schedule_id', 'schedules', 'id', 'SET NULL', 'CASCADE');
$this->forge->addForeignKey('device_id', 'devices', 'id', 'CASCADE', 'CASCADE');
$this->forge->createTable('attendance_sessions');
}
public function down()
{
$this->forge->dropTable('attendance_sessions');
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateParentsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'name' => [
'type' => 'VARCHAR',
'constraint' => '255',
],
'phone_number' => [
'type' => 'VARCHAR',
'constraint' => '20',
'null' => true,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('parents');
}
public function down()
{
$this->forge->dropTable('parents');
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateTelegramAccountsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'telegram_user_id' => [
'type' => 'BIGINT',
'constraint' => 20,
'unsigned' => true,
'unique' => true,
],
'username' => [
'type' => 'VARCHAR',
'constraint' => '255',
'null' => true,
],
'first_name' => [
'type' => 'VARCHAR',
'constraint' => '255',
'null' => true,
],
'last_name' => [
'type' => 'VARCHAR',
'constraint' => '255',
'null' => true,
],
'is_verified' => [
'type' => 'TINYINT',
'constraint' => 1,
'default' => 0,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('telegram_accounts');
}
public function down()
{
$this->forge->dropTable('telegram_accounts');
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateStudentParentsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'student_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'parent_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'relationship' => [
'type' => 'ENUM',
'constraint' => ['AYAH', 'IBU', 'WALI'],
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addKey(['student_id', 'parent_id']);
$this->forge->addForeignKey('student_id', 'students', 'id', 'CASCADE', 'CASCADE');
$this->forge->addForeignKey('parent_id', 'parents', 'id', 'CASCADE', 'CASCADE');
$this->forge->createTable('student_parents');
}
public function down()
{
$this->forge->dropTable('student_parents');
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddParentLinkCodeToStudentsTable extends Migration
{
public function up()
{
$fields = [
'parent_link_code' => [
'type' => 'VARCHAR',
'constraint' => '16',
'null' => true,
'unique' => true,
'after' => 'class_id',
],
];
$this->forge->addColumn('students', $fields);
}
public function down()
{
$this->forge->dropColumn('students', 'parent_link_code');
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddParentIdToTelegramAccountsTable extends Migration
{
public function up()
{
$this->forge->addColumn('telegram_accounts', [
'parent_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'null' => true,
'after' => 'is_verified',
],
]);
$this->forge->addForeignKey('parent_id', 'parents', 'id', 'CASCADE', 'SET NULL', 'telegram_accounts_parent_id_fk');
}
public function down()
{
$this->forge->dropForeignKey('telegram_accounts', 'telegram_accounts_parent_id_fk');
$this->forge->dropColumn('telegram_accounts', 'parent_id');
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateUsersTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'name' => [
'type' => 'VARCHAR',
'constraint' => '255',
],
'email' => [
'type' => 'VARCHAR',
'constraint' => '255',
'unique' => true,
],
'password_hash' => [
'type' => 'VARCHAR',
'constraint' => '255',
],
'is_active' => [
'type' => 'TINYINT',
'constraint' => 1,
'default' => 1,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('users');
}
public function down()
{
$this->forge->dropTable('users');
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateRolesTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'role_code' => [
'type' => 'VARCHAR',
'constraint' => '50',
'unique' => true,
],
'role_name' => [
'type' => 'VARCHAR',
'constraint' => '100',
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('roles');
}
public function down()
{
$this->forge->dropTable('roles');
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateUserRolesTable extends Migration
{
public function up()
{
$this->forge->addField([
'user_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'role_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
]);
$this->forge->addKey(['user_id', 'role_id'], true);
$this->forge->addForeignKey('user_id', 'users', 'id', 'CASCADE', 'CASCADE');
$this->forge->addForeignKey('role_id', 'roles', 'id', 'CASCADE', 'CASCADE');
$this->forge->createTable('user_roles');
}
public function down()
{
$this->forge->dropTable('user_roles');
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddUserIdToParentsTable extends Migration
{
public function up()
{
$this->forge->addColumn('parents', [
'user_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'null' => true,
'after' => 'id',
],
]);
$this->forge->addForeignKey('user_id', 'users', 'id', 'SET NULL', 'CASCADE', 'parents_user_id_fk');
}
public function down()
{
$this->forge->dropForeignKey('parents', 'parents_user_id_fk');
$this->forge->dropColumn('parents', 'user_id');
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddWaliUserIdToClassesTable extends Migration
{
public function up()
{
$this->forge->addColumn('classes', [
'wali_user_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'null' => true,
'after' => 'grade',
],
]);
$this->forge->addForeignKey('wali_user_id', 'users', 'id', 'SET NULL', 'CASCADE', 'classes_wali_user_id_fk');
}
public function down()
{
$this->forge->dropForeignKey('classes', 'classes_wali_user_id_fk');
$this->forge->dropColumn('classes', 'wali_user_id');
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddTeacherUserIdToSchedulesTable extends Migration
{
public function up()
{
$this->forge->addColumn('schedules', [
'teacher_user_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'null' => true,
'after' => 'teacher_name',
],
]);
$this->forge->addForeignKey('teacher_user_id', 'users', 'id', 'SET NULL', 'CASCADE', 'schedules_teacher_user_id_fk');
}
public function down()
{
$this->forge->dropForeignKey('schedules', 'schedules_teacher_user_id_fk');
$this->forge->dropColumn('schedules', 'teacher_user_id');
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddAttendanceDateAndUniqueToAttendanceSessionsTable extends Migration
{
public function up()
{
$this->forge->addColumn('attendance_sessions', [
'attendance_date' => [
'type' => 'DATE',
'null' => true,
'after' => 'schedule_id',
],
]);
$this->db->query('UPDATE attendance_sessions SET attendance_date = DATE(checkin_at) WHERE attendance_date IS NULL');
$this->forge->modifyColumn('attendance_sessions', [
'attendance_date' => [
'type' => 'DATE',
'null' => false,
'after' => 'schedule_id',
],
]);
$prefix = $this->db->DBPrefix;
$table = $this->db->escapeIdentifiers($prefix . 'attendance_sessions');
$this->db->query('ALTER TABLE ' . $table . ' ADD UNIQUE KEY unique_student_schedule_date (student_id, schedule_id, attendance_date)');
}
public function down()
{
$prefix = $this->db->DBPrefix;
$table = $this->db->escapeIdentifiers($prefix . 'attendance_sessions');
$this->db->query('ALTER TABLE ' . $table . ' DROP KEY unique_student_schedule_date');
$this->forge->dropColumn('attendance_sessions', 'attendance_date');
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateLessonSlotsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'slot_number' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'start_time' => [
'type' => 'TIME',
],
'end_time' => [
'type' => 'TIME',
],
'is_active' => [
'type' => 'TINYINT',
'constraint' => 1,
'default' => 1,
],
]);
$this->forge->addKey('id', true);
$this->forge->addUniqueKey('slot_number');
$this->forge->createTable('lesson_slots');
}
public function down()
{
$this->forge->dropTable('lesson_slots');
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddLessonSlotIdAndUniqueToSchedulesTable extends Migration
{
public function up()
{
$this->forge->addColumn('schedules', [
'lesson_slot_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'null' => true,
'after' => 'teacher_user_id',
],
'is_active' => [
'type' => 'TINYINT',
'constraint' => 1,
'default' => 1,
'after' => 'room',
],
]);
$this->forge->addForeignKey('lesson_slot_id', 'lesson_slots', 'id', 'SET NULL', 'CASCADE', 'schedules_lesson_slot_id_fk');
$this->forge->addUniqueKey(['class_id', 'lesson_slot_id', 'day_of_week'], 'schedules_class_slot_day_unique');
}
public function down()
{
$this->forge->dropForeignKey('schedules', 'schedules_lesson_slot_id_fk');
$this->forge->dropKey('schedules', 'schedules_class_slot_day_unique');
$this->forge->dropColumn('schedules', 'lesson_slot_id');
$this->forge->dropColumn('schedules', 'is_active');
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddMajorToClassesTable extends Migration
{
public function up()
{
$this->forge->addColumn('classes', [
'major' => [
'type' => 'VARCHAR',
'constraint' => 50,
'null' => false,
'default' => 'IPA',
'after' => 'grade',
],
]);
}
public function down()
{
$this->forge->dropColumn('classes', 'major');
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddCodeToSubjectsTable extends Migration
{
public function up()
{
$this->forge->addColumn('subjects', [
'code' => [
'type' => 'VARCHAR',
'constraint' => 50,
'null' => true,
'after' => 'name',
],
]);
}
public function down()
{
$this->forge->dropColumn('subjects', 'code');
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddStudentFieldsForManagement extends Migration
{
public function up()
{
// Rename nis -> nisn (Dapodik compatible; unique index follows column rename)
$this->db->query('ALTER TABLE ' . $this->db->prefixTable('students') . ' CHANGE nis nisn VARCHAR(50) NOT NULL');
// Add gender (L/P)
$this->forge->addColumn('students', [
'gender' => [
'type' => 'VARCHAR',
'constraint' => 1,
'null' => true,
'after' => 'name',
],
]);
// Add is_active (default 1)
$this->forge->addColumn('students', [
'is_active' => [
'type' => 'TINYINT',
'constraint' => 1,
'default' => 1,
'after' => 'class_id',
],
]);
// Make class_id nullable (for unmapped / Dapodik sync)
$this->forge->dropForeignKey('students', 'students_class_id_foreign');
$this->forge->modifyColumn('students', [
'class_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'null' => true,
],
]);
$this->forge->addForeignKey('class_id', 'classes', 'id', 'SET NULL', 'CASCADE', 'students_class_id_foreign');
}
public function down()
{
$this->forge->dropForeignKey('students', 'students_class_id_foreign');
$this->forge->modifyColumn('students', [
'class_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'null' => false,
],
]);
$this->forge->addForeignKey('class_id', 'classes', 'id', 'CASCADE', 'CASCADE', 'students_class_id_foreign');
$this->forge->dropColumn('students', 'is_active');
$this->forge->dropColumn('students', 'gender');
$this->db->query('ALTER TABLE ' . $this->db->prefixTable('students') . ' CHANGE nisn nis VARCHAR(50) NOT NULL');
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateDapodikRombelMappingsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'dapodik_rombel' => [
'type' => 'VARCHAR',
'constraint' => 100,
],
'class_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'null' => true,
],
'last_seen_at' => [
'type' => 'DATETIME',
'null' => true,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addUniqueKey('dapodik_rombel');
$this->forge->addForeignKey('class_id', 'classes', 'id', 'SET NULL', 'CASCADE', 'dapodik_rombel_mappings_class_id_fk');
$this->forge->createTable('dapodik_rombel_mappings');
}
public function down()
{
$this->forge->dropTable('dapodik_rombel_mappings');
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateDapodikSyncJobsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'BIGINT',
'constraint' => 20,
'unsigned' => true,
'auto_increment' => true,
],
'type' => [
'type' => 'VARCHAR',
'constraint' => 50,
'comment' => 'students|classes',
],
'total_rows' => [
'type' => 'INT',
'constraint' => 11,
'default' => 0,
],
'processed_rows' => [
'type' => 'INT',
'constraint' => 11,
'default' => 0,
],
'status' => [
'type' => 'VARCHAR',
'constraint' => 20,
'default' => 'pending',
'comment' => 'pending|running|completed|failed',
],
'message' => [
'type' => 'TEXT',
'null' => true,
],
'started_at' => [
'type' => 'DATETIME',
'null' => true,
],
'finished_at' => [
'type' => 'DATETIME',
'null' => true,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addKey('status');
$this->forge->createTable('dapodik_sync_jobs');
}
public function down()
{
$this->forge->dropTable('dapodik_sync_jobs');
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddDapodikIdToStudentsTable extends Migration
{
public function up()
{
// Add dapodik_id column (nullable, unique) to students
$this->forge->addColumn('students', [
'dapodik_id' => [
'type' => 'VARCHAR',
'constraint' => 64,
'null' => true,
'after' => 'id',
],
]);
// Add unique index on dapodik_id (for upsert)
$this->db->query('CREATE UNIQUE INDEX students_dapodik_id_unique ON ' . $this->db->prefixTable('students') . ' (dapodik_id)');
}
public function down()
{
// Drop unique index and column
$this->db->query('DROP INDEX students_dapodik_id_unique ON ' . $this->db->prefixTable('students'));
$this->forge->dropColumn('students', 'dapodik_id');
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateTeacherSubjectsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'teacher_user_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'subject_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addUniqueKey(['teacher_user_id', 'subject_id'], 'teacher_subjects_unique');
$this->forge->addForeignKey('teacher_user_id', 'users', 'id', 'CASCADE', 'CASCADE', 'teacher_subjects_teacher_fk');
$this->forge->addForeignKey('subject_id', 'subjects', 'id', 'CASCADE', 'CASCADE', 'teacher_subjects_subject_fk');
$this->forge->createTable('teacher_subjects');
}
public function down()
{
$this->forge->dropForeignKey('teacher_subjects', 'teacher_subjects_teacher_fk');
$this->forge->dropForeignKey('teacher_subjects', 'teacher_subjects_subject_fk');
$this->forge->dropTable('teacher_subjects');
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddFaceExternalIdToStudentsTable extends Migration
{
public function up()
{
// Add nullable face_external_id column for linking to external face-recognition ID
$this->forge->addColumn('students', [
'face_external_id' => [
'type' => 'VARCHAR',
'constraint' => 100,
'null' => true,
'after' => 'dapodik_id',
],
]);
// Unique index so one face ID hanya milik satu siswa
$this->forge->addUniqueKey('face_external_id', 'students_face_external_id_unique');
}
public function down()
{
$this->forge->dropKey('students', 'students_face_external_id_unique');
$this->forge->dropColumn('students', 'face_external_id');
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateStudentMobileAccountsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'student_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'pin_hash' => [
'type' => 'VARCHAR',
'constraint' => 255,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addUniqueKey('student_id');
$this->forge->addForeignKey('student_id', 'students', 'id', 'CASCADE', 'CASCADE', 'student_mobile_accounts_student_fk');
$this->forge->createTable('student_mobile_accounts');
}
public function down()
{
$this->forge->dropTable('student_mobile_accounts');
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateViolationCategoriesTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'code' => [
'type' => 'VARCHAR',
'constraint' => 10,
],
'name' => [
'type' => 'VARCHAR',
'constraint' => 100,
],
'description' => [
'type' => 'TEXT',
'null' => true,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addUniqueKey('code', 'violation_categories_code_unique');
$this->forge->createTable('violation_categories');
}
public function down()
{
$this->forge->dropTable('violation_categories');
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateViolationsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'category_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'code' => [
'type' => 'VARCHAR',
'constraint' => 20,
'null' => true,
],
'title' => [
'type' => 'VARCHAR',
'constraint' => 255,
],
'description' => [
'type' => 'TEXT',
'null' => true,
],
'score' => [
'type' => 'INT',
'constraint' => 11,
'default' => 0,
],
'is_active' => [
'type' => 'TINYINT',
'constraint' => 1,
'default' => 1,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addForeignKey('category_id', 'violation_categories', 'id', 'CASCADE', 'CASCADE', 'violations_category_fk');
$this->forge->createTable('violations');
}
public function down()
{
$this->forge->dropForeignKey('violations', 'violations_category_fk');
$this->forge->dropTable('violations');
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateStudentViolationsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'student_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'class_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'null' => true,
],
'violation_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'reported_by_user_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'occurred_at' => [
'type' => 'DATETIME',
'null' => true,
],
'notes' => [
'type' => 'TEXT',
'null' => true,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addKey('student_id');
$this->forge->addKey('class_id');
$this->forge->addKey('occurred_at');
$this->forge->addForeignKey('student_id', 'students', 'id', 'CASCADE', 'CASCADE', 'student_violations_student_fk');
$this->forge->addForeignKey('class_id', 'classes', 'id', 'SET NULL', 'CASCADE', 'student_violations_class_fk');
$this->forge->addForeignKey('violation_id', 'violations', 'id', 'CASCADE', 'CASCADE', 'student_violations_violation_fk');
$this->forge->addForeignKey('reported_by_user_id', 'users', 'id', 'CASCADE', 'CASCADE', 'student_violations_reporter_fk');
$this->forge->createTable('student_violations');
}
public function down()
{
$this->forge->dropForeignKey('student_violations', 'student_violations_student_fk');
$this->forge->dropForeignKey('student_violations', 'student_violations_class_fk');
$this->forge->dropForeignKey('student_violations', 'student_violations_violation_fk');
$this->forge->dropForeignKey('student_violations', 'student_violations_reporter_fk');
$this->forge->dropTable('student_violations');
}
}

View File

@@ -0,0 +1,146 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
/**
* Seed awal master pelanggaran berdasarkan tabel tata tertib
* yang kamu kirim (kategori AI + tindak pidana).
*
* Catatan: migration ini hanya menambah data jika belum ada
* (dicek berdasarkan code kategori + title pelanggaran).
*/
class SeedViolationsFromPolicy extends Migration
{
public function up()
{
$db = \Config\Database::connect();
// 1) Pastikan kategori ada
$categories = [
'A' => ['name' => 'KETERLAMBATAN & KEHADIRAN'],
'B' => ['name' => 'PAKAIAN'],
'C' => ['name' => 'KEPRIBADIAN'],
'D' => ['name' => 'KETERTIBAN'],
'E' => ['name' => 'MEROKOK'],
'F' => ['name' => 'PORNOGRAFI'],
'G' => ['name' => 'SENJATA TAJAM'],
'H' => ['name' => 'NAPZA DAN / MINUMAN KERAS'],
'I' => ['name' => 'BERKELAHI / TAWURAN'],
'J' => ['name' => 'TINDAK PIDANA HUKUM'],
];
$catIds = [];
foreach ($categories as $code => $cfg) {
$row = $db->table('violation_categories')->where('code', $code)->get()->getRowArray();
if (! $row) {
$db->table('violation_categories')->insert([
'code' => $code,
'name' => $cfg['name'],
'description' => null,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
$catIds[$code] = (int) $db->insertID();
} else {
$catIds[$code] = (int) $row['id'];
}
}
// Helper untuk insert jika belum ada (berdasarkan title)
$insertViolation = function (string $code, string $title, int $score, ?string $description = null) use ($db, $catIds): void {
if (! isset($catIds[$code])) {
return;
}
$exists = $db->table('violations')
->where('category_id', $catIds[$code])
->where('title', $title)
->countAllResults();
if ($exists > 0) {
return;
}
$db->table('violations')->insert([
'category_id' => $catIds[$code],
'code' => null,
'title' => $title,
'description' => $description,
'score' => $score,
'is_active' => 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
};
// 2) Seed pelanggaran per kategori (ringkas dari tabel yang kamu kirim)
// A — Keterlambatan & Kehadiran
$insertViolation('A', 'Terlambat (dipulangkan dicatat tidak hadir tanpa keterangan)', 5);
$insertViolation('A', 'Tidak masuk tanpa keterangan', 5);
$insertViolation('A', 'Tidak masuk dengan membuat keterangan palsu', 10);
$insertViolation('A', 'Tidak mengikuti jam pelajaran tertentu', 5);
$insertViolation('A', 'Keluar saat pelajaran berlangsung dan tidak kembali sampai pulang', 5);
$insertViolation('A', 'Tidak ikut upacara bendera', 5);
$insertViolation('A', 'Meninggalkan pelajaran atau sekolah dengan izin palsu', 10);
// B — Pakaian
$insertViolation('B', 'Memakai seragam tidak sesuai aturan (teguran 1)', 2);
$insertViolation('B', 'Memakai seragam tidak sesuai aturan (teguran 2 + surat pernyataan 1)', 2);
$insertViolation('B', 'Memakai seragam tidak sesuai aturan (teguran 3 + sanksi sekolah)', 2);
$insertViolation('B', 'Tidak memakai seragam sekolah sesuai jadwal', 3);
// C — Kepribadian
$insertViolation('C', 'Berhias berlebihan', 5);
$insertViolation('C', 'Siswa putra memakai gelang, kalung, anting', 10);
$insertViolation('C', 'Memakai tindik di wajah atau tubuh lain (siswi)', 10);
$insertViolation('C', 'Memakai tato / atribut tidak wajar bagi pelajar', 20);
$insertViolation('C', 'Berduaan/bermesraan/pacaran (tindak asusila, melanggar kesopanan)', 50);
$insertViolation('C', 'Melawan kepala sekolah/guru/karyawan dengan ancaman', 75);
$insertViolation('C', 'Melawan kepala sekolah/guru/karyawan dengan pemukulan', 100);
$insertViolation('C', 'Intimidasi / bullying dengan kekerasan', 75);
$insertViolation('C', 'Tindakan tidak menyenangkan sesama siswa', 15);
$insertViolation('C', 'Mengaktifkan HP saat KBM berlangsung', 5);
$insertViolation('C', 'Mencemarkan nama kepala sekolah/guru/karyawan/sekolah', 50);
$insertViolation('C', 'Diketahui hamil / menikah', 100);
// D — Ketertiban
$insertViolation('D', 'Mengotori / mencoret benda milik sekolah/guru/karyawan/teman/lingkungan', 15);
$insertViolation('D', 'Merusak atau mengambil barang milik sekolah/guru/karyawan/teman', 50);
$insertViolation('D', 'Membawa/menggunakan benda tak terkait KBM tanpa izin', 15);
$insertViolation('D', 'Memakai sandal/sepatu sandal saat pelajaran tanpa izin', 5);
$insertViolation('D', 'Melompat pagar sekolah untuk keluar/masuk', 20);
$insertViolation('D', 'Tidak membuang sampah pada tempatnya', 3);
$insertViolation('D', 'Merusak tanaman dengan sengaja', 5);
// E — Merokok
$insertViolation('E', 'Membawa rokok ke sekolah', 20);
$insertViolation('E', 'Menghisap rokok di sekolah', 25);
// F — Pornografi
$insertViolation('F', 'Memiliki/membawa/mempergunakan media berkonten pornografi/kekerasan', 65);
$insertViolation('F', 'Memperjualbelikan media berkonten pornografi/kekerasan', 75);
// G — Senjata tajam
$insertViolation('G', 'Membawa senjata tajam/api/bahan peledak tanpa izin', 100);
$insertViolation('G', 'Memperjualbelikan senjata tajam/api/bahan peledak', 100);
$insertViolation('G', 'Menggunakan senjata tajam/api/bahan peledak untuk mengancam/melukai', 100);
// H — NAPZA / minuman keras
$insertViolation('H', 'Menggunakan napza dan/atau minuman terlarang', 100);
$insertViolation('H', 'Membawa napza dan/atau minuman terlarang', 100);
$insertViolation('H', 'Mengedarkan/memperjualbelikan napza/minuman keras', 100);
// I — Berkelahi / tawuran
$insertViolation('I', 'Indikasi / berkelahi / tawuran dengan siswa sekolah lain', 100);
$insertViolation('I', 'Berkelahi antar siswa', 100);
// J — Tindak pidana hukum lain
$insertViolation('J', 'Tersangkut tindak pidana lainnya', 10);
}
public function down()
{
// Tidak perlu menghapus data seed; biarkan tetap ada.
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateDisciplineLevelsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'min_score' => [
'type' => 'INT',
'constraint' => 11,
'default' => 0,
],
'max_score' => [
'type' => 'INT',
'constraint' => 11,
'null' => true, // null = tak terbatas (>= min_score)
],
'title' => [
'type' => 'VARCHAR',
'constraint' => 100,
],
'school_action' => [
'type' => 'TEXT',
'null' => true,
],
'executor' => [
'type' => 'VARCHAR',
'constraint' => 150,
'null' => true,
],
'is_active' => [
'type' => 'TINYINT',
'constraint' => 1,
'default' => 1,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('discipline_levels');
}
public function down()
{
$this->forge->dropTable('discipline_levels');
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
/**
* Seed awal level disiplin berdasarkan rentang poin dan tindakan sekolah.
*/
class SeedDisciplineLevelsFromPolicy extends Migration
{
public function up()
{
$db = \Config\Database::connect();
$levels = [
[
'min_score' => 1,
'max_score' => 40,
'title' => 'Level 1',
'school_action'=> "Berkomunikasi dengan orang tua/wali siswa.\nTeguran tertulis dan surat perjanjian pertama.",
'executor' => 'Wali kelas',
],
[
'min_score' => 41,
'max_score' => 70,
'title' => 'Level 2',
'school_action'=> "Memberi bimbingan dan perhatian.\nTeguran tertulis dan surat perjanjian kedua.",
'executor' => 'Wali kelas dan BK',
],
[
'min_score' => 71,
'max_score' => 99,
'title' => 'Level 3',
'school_action'=> "Berkomunikasi dengan orang tua/wali siswa.\nMemberi bimbingan dan perhatian.\nSurat perjanjian tertulis bermaterai.\nSkorsing maksimal 3 hari efektif, diketahui Kepala Sekolah.",
'executor' => 'Wali kelas, BK, wakasek kesiswaan, diketahui Kepala Sekolah',
],
[
'min_score' => 100,
'max_score' => null,
'title' => 'Level 4',
'school_action'=> "Berkomunikasi dengan orang tua/wali siswa.\nMemberi bimbingan dan perhatian.\nDikembalikan kepada orang tua secara sepihak.",
'executor' => 'Pleno guru',
],
];
foreach ($levels as $lvl) {
// Cegah duplikat berdasarkan min_score & max_score
$exists = $db->table('discipline_levels')
->where('min_score', $lvl['min_score'])
->where('max_score', $lvl['max_score'])
->countAllResults();
if ($exists > 0) {
continue;
}
$db->table('discipline_levels')->insert([
'min_score' => $lvl['min_score'],
'max_score' => $lvl['max_score'],
'title' => $lvl['title'],
'school_action'=> $lvl['school_action'],
'executor' => $lvl['executor'],
'is_active' => 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
}
}
public function down()
{
// Tidak menghapus data; biarkan tetap ada.
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddGeoFenceToDevicesTable extends Migration
{
public function up()
{
$fields = [
'latitude' => [
'type' => 'DECIMAL',
'constraint' => '10,8',
'null' => true,
'after' => 'last_seen_at',
],
'longitude' => [
'type' => 'DECIMAL',
'constraint' => '11,8',
'null' => true,
'after' => 'latitude',
],
'radius_meters' => [
'type' => 'INT',
'constraint' => 11,
'null' => true,
'after' => 'longitude',
],
];
$this->forge->addColumn('devices', $fields);
}
public function down()
{
$this->forge->dropColumn('devices', ['latitude', 'longitude', 'radius_meters']);
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
/**
* Satu set pengaturan presensi terpusat: jam masuk & jam pulang sekolah.
* Koordinat sekolah tetap di table zones (SMA1-SCHOOL).
*/
class CreateSchoolPresenceSettingsTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'time_masuk_start' => [
'type' => 'TIME',
'null' => true,
'comment' => 'Mulai window absen masuk (misal 06:30)',
],
'time_masuk_end' => [
'type' => 'TIME',
'null' => true,
'comment' => 'Akhir window absen masuk (misal 07:00)',
],
'time_pulang_start' => [
'type' => 'TIME',
'null' => true,
'comment' => 'Mulai window absen pulang (misal 14:00)',
],
'time_pulang_end' => [
'type' => 'TIME',
'null' => true,
'comment' => 'Akhir window absen pulang (misal 14:30)',
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->createTable('school_presence_settings');
// Satu row default
$this->db->table('school_presence_settings')->insert([
'time_masuk_start' => '06:30:00',
'time_masuk_end' => '07:00:00',
'time_pulang_start' => '14:00:00',
'time_pulang_end' => '14:30:00',
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
}
public function down()
{
$this->forge->dropTable('school_presence_settings');
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
/**
* Token untuk absen mapel via QR: guru generate, siswa scan.
*/
class CreateQrAttendanceTokensTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'schedule_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'token' => [
'type' => 'VARCHAR',
'constraint' => 64,
],
'expires_at' => [
'type' => 'DATETIME',
],
'created_by_user_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'null' => true,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addUniqueKey('token');
$this->forge->addKey('expires_at');
$this->forge->addKey('schedule_id');
$this->forge->addForeignKey('schedule_id', 'schedules', 'id', 'CASCADE', 'CASCADE');
$this->forge->createTable('qr_attendance_tokens');
}
public function down()
{
$this->forge->dropTable('qr_attendance_tokens');
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
/**
* Menambah checkin_type untuk membedakan absen mapel vs masuk/pulang.
* mapel = absen per jadwal (default); masuk = absen masuk sekolah; pulang = absen pulang.
*/
class AddCheckinTypeToAttendanceSessions extends Migration
{
public function up()
{
$this->forge->addColumn('attendance_sessions', [
'checkin_type' => [
'type' => 'ENUM',
'constraint' => ['mapel', 'masuk', 'pulang'],
'default' => 'mapel',
'null' => false,
'after' => 'schedule_id',
],
]);
}
public function down()
{
$this->forge->dropColumn('attendance_sessions', 'checkin_type');
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddFaceHashToStudentsTable extends Migration
{
public function up()
{
$this->forge->addColumn('students', [
'face_hash' => [
'type' => 'VARCHAR',
'constraint' => 32,
'null' => true,
'after' => 'face_external_id',
'comment' => 'MD5 hash dari file foto wajah referensi',
],
]);
}
public function down()
{
$this->forge->dropColumn('students', 'face_hash');
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateStudentFacesTable extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
'auto_increment' => true,
],
'student_id' => [
'type' => 'INT',
'constraint' => 11,
'unsigned' => true,
],
'embedding' => [
'type' => 'LONGTEXT',
'null' => false,
'comment' => 'JSON string float[] embedding wajah',
],
'source' => [
'type' => 'ENUM',
'constraint' => ['formal', 'live', 'live_avg'],
'default' => 'formal',
],
'quality_score' => [
'type' => 'FLOAT',
'null' => true,
],
'created_at' => [
'type' => 'DATETIME',
'null' => true,
],
'updated_at' => [
'type' => 'DATETIME',
'null' => true,
],
]);
$this->forge->addKey('id', true);
$this->forge->addKey('student_id');
$this->forge->addForeignKey('student_id', 'students', 'id', 'CASCADE', 'CASCADE', 'student_faces_student_fk');
$this->forge->createTable('student_faces');
}
public function down()
{
$this->forge->dropTable('student_faces');
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddPhotoFormalUrlToStudentsTable extends Migration
{
public function up()
{
$this->forge->addColumn('students', [
'photo_formal_url' => [
'type' => 'VARCHAR',
'constraint' => 255,
'null' => true,
'after' => 'face_hash',
'comment' => 'URL/path foto formal administrasi (mis. dari Drive)',
],
]);
}
public function down()
{
$this->forge->dropColumn('students', 'photo_formal_url');
}
}