recreate project
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
// 2025-09-10-031001_CreateEmailTemplates.php
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
use CodeIgniter\Database\RawSql;
|
||||
|
||||
class CreateEmailTemplates extends Migration
|
||||
{
|
||||
protected $DBGroup = 'default';
|
||||
|
||||
public function up()
|
||||
{
|
||||
$this->forge->addField([
|
||||
'id' => ['type'=>'INT','unsigned'=>true,'auto_increment'=>true],
|
||||
'template_key' => ['type'=>'VARCHAR','constraint'=>64,'null'=>false],
|
||||
'name' => ['type'=>'VARCHAR','constraint'=>100,'null'=>false],
|
||||
'subject' => ['type'=>'VARCHAR','constraint'=>255,'null'=>false],
|
||||
'body' => ['type'=>'MEDIUMTEXT','null'=>false],
|
||||
'is_active' => ['type'=>'TINYINT','constraint'=>1,'default'=>1,'null'=>false],
|
||||
'created_at' => ['type'=>'DATETIME','null'=>false,'default'=>new RawSql('CURRENT_TIMESTAMP')],
|
||||
'updated_at' => ['type'=>'DATETIME','null'=>false,'default'=>new RawSql('CURRENT_TIMESTAMP')],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey('template_key');
|
||||
|
||||
$this->forge->createTable('email_templates', true, [
|
||||
'ENGINE'=>'InnoDB','DEFAULT CHARSET'=>'utf8mb4','COLLATE'=>'utf8mb4_unicode_ci',
|
||||
]);
|
||||
|
||||
// Add ON UPDATE for updated_at after table creation
|
||||
$this->db->query("ALTER TABLE `email_templates`
|
||||
MODIFY `updated_at` DATETIME NOT NULL
|
||||
DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->forge->dropTable('email_templates', true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
// 2025-09-10-031010_CreateFamilies.php
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
use CodeIgniter\Database\RawSql;
|
||||
|
||||
class CreateFamilies extends Migration
|
||||
{
|
||||
protected $DBGroup = 'default';
|
||||
|
||||
public function up()
|
||||
{
|
||||
$this->forge->addField([
|
||||
'id' => ['type'=>'INT','unsigned'=>true,'auto_increment'=>true],
|
||||
'family_code' => ['type'=>'VARCHAR','constraint'=>32,'null'=>true],
|
||||
'household_name' => ['type'=>'VARCHAR','constraint'=>120,'null'=>true],
|
||||
'address_line1' => ['type'=>'VARCHAR','constraint'=>150,'null'=>true],
|
||||
'address_line2' => ['type'=>'VARCHAR','constraint'=>150,'null'=>true],
|
||||
'city' => ['type'=>'VARCHAR','constraint'=>80,'null'=>true],
|
||||
'state' => ['type'=>'VARCHAR','constraint'=>40,'null'=>true],
|
||||
'postal_code' => ['type'=>'VARCHAR','constraint'=>20,'null'=>true],
|
||||
'country' => ['type'=>'VARCHAR','constraint'=>2,'null'=>true],
|
||||
'primary_phone' => ['type'=>'VARCHAR','constraint'=>40,'null'=>true],
|
||||
'preferred_lang' => ['type'=>'VARCHAR','constraint'=>10,'default'=>'en','null'=>false],
|
||||
'preferred_contact_method' => ['type'=>'ENUM','constraint'=>['email','sms','phone'],'default'=>'email','null'=>false],
|
||||
'is_active' => ['type'=>'TINYINT','constraint'=>1,'default'=>1,'null'=>false],
|
||||
'created_at' => ['type'=>'DATETIME','null'=>false,'default'=>new RawSql('CURRENT_TIMESTAMP')],
|
||||
'updated_at' => ['type'=>'DATETIME','null'=>false,'default'=>new RawSql('CURRENT_TIMESTAMP')],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey('family_code');
|
||||
|
||||
$this->forge->createTable('families', true, [
|
||||
'ENGINE'=>'InnoDB','DEFAULT CHARSET'=>'utf8mb4','COLLATE'=>'utf8mb4_unicode_ci',
|
||||
]);
|
||||
|
||||
$this->db->query("ALTER TABLE `families`
|
||||
MODIFY `updated_at` DATETIME NOT NULL
|
||||
DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->forge->dropTable('families', true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
// 2025-09-10-031020_CreateFamilyStudents.php
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class CreateFamilyStudents extends Migration
|
||||
{
|
||||
protected $DBGroup = 'default';
|
||||
|
||||
public function up()
|
||||
{
|
||||
if (! $this->db->tableExists('families') || ! $this->db->tableExists('students')) {
|
||||
throw new \RuntimeException('CreateFamilyStudents requires families and students tables to exist.');
|
||||
}
|
||||
|
||||
$this->forge->addField([
|
||||
'id' => ['type'=>'INT','unsigned'=>true,'auto_increment'=>true],
|
||||
'family_id' => ['type'=>'INT','unsigned'=>true,'null'=>false],
|
||||
'student_id' => ['type'=>'INT','unsigned'=>true,'null'=>false],
|
||||
'is_primary_home' => ['type'=>'TINYINT','constraint'=>1,'default'=>1],
|
||||
'notes' => ['type'=>'VARCHAR','constraint'=>255,'null'=>true],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey(['family_id','student_id'], 'uq_family_student');
|
||||
$this->forge->addKey('student_id'); // no name param
|
||||
$this->forge->addForeignKey('family_id','families','id','CASCADE','CASCADE','fk_fs_family');
|
||||
$this->forge->addForeignKey('student_id','students','id','CASCADE','CASCADE','fk_fs_student');
|
||||
|
||||
$this->forge->createTable('family_students', true, [
|
||||
'ENGINE'=>'InnoDB','DEFAULT CHARSET'=>'utf8mb4','COLLATE'=>'utf8mb4_unicode_ci',
|
||||
]);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->forge->dropTable('family_students', true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
// 2025-09-10-031030_CreateFamilyCommPrefs.php
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class CreateFamilyCommPrefs extends Migration
|
||||
{
|
||||
protected $DBGroup = 'default';
|
||||
|
||||
public function up()
|
||||
{
|
||||
if (! $this->db->tableExists('families')) {
|
||||
throw new \RuntimeException('CreateFamilyCommPrefs requires families table to exist.');
|
||||
}
|
||||
|
||||
$this->forge->addField([
|
||||
'id' => ['type'=>'INT','unsigned'=>true,'auto_increment'=>true],
|
||||
'family_id' => ['type'=>'INT','unsigned'=>true,'null'=>false],
|
||||
'category' => ['type'=>'ENUM','constraint'=>['attendance','grade','behavior','general'],'null'=>false],
|
||||
'via_email' => ['type'=>'TINYINT','constraint'=>1,'default'=>1],
|
||||
'via_sms' => ['type'=>'TINYINT','constraint'=>1,'default'=>0],
|
||||
'cc_all_guardians' => ['type'=>'TINYINT','constraint'=>1,'default'=>1],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey(['family_id','category'], 'uq_family_category');
|
||||
$this->forge->addForeignKey('family_id','families','id','CASCADE','CASCADE','fk_fcp_family');
|
||||
|
||||
$this->forge->createTable('family_comm_prefs', true, [
|
||||
'ENGINE'=>'InnoDB','DEFAULT CHARSET'=>'utf8mb4','COLLATE'=>'utf8mb4_unicode_ci',
|
||||
]);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->forge->dropTable('family_comm_prefs', true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
// 2025-09-10-031040_CreateCommunicationLogs.php
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
use CodeIgniter\Database\RawSql;
|
||||
|
||||
class CreateCommunicationLogs extends Migration
|
||||
{
|
||||
protected $DBGroup = 'default';
|
||||
|
||||
public function up()
|
||||
{
|
||||
if (! $this->db->tableExists('families')) {
|
||||
throw new \RuntimeException('CreateCommunicationLogs requires families table to exist.');
|
||||
}
|
||||
|
||||
$this->forge->addField([
|
||||
'id' => ['type'=>'BIGINT','unsigned'=>true,'auto_increment'=>true],
|
||||
'student_id' => ['type'=>'INT','unsigned'=>true,'null'=>false],
|
||||
'family_id' => ['type'=>'INT','unsigned'=>true,'null'=>true], // SET NULL on delete
|
||||
'student_name' => ['type'=>'VARCHAR','constraint'=>150,'null'=>false],
|
||||
'template_key' => ['type'=>'VARCHAR','constraint'=>64,'null'=>false],
|
||||
'subject' => ['type'=>'VARCHAR','constraint'=>255,'null'=>false],
|
||||
'body' => ['type'=>'MEDIUMTEXT','null'=>false],
|
||||
'recipients' => ['type'=>'TEXT','null'=>false],
|
||||
'cc' => ['type'=>'TEXT','null'=>true],
|
||||
'bcc' => ['type'=>'TEXT','null'=>true],
|
||||
'attachments' => ['type'=>'TEXT','null'=>true],
|
||||
'status' => ['type'=>'ENUM','constraint'=>['sent','failed'],'null'=>false],
|
||||
'error_message' => ['type'=>'TEXT','null'=>true],
|
||||
'sent_by' => ['type'=>'INT','unsigned'=>true,'null'=>true],
|
||||
'metadata' => ['type'=>'JSON','null'=>true],
|
||||
'created_at' => ['type'=>'DATETIME','null'=>false,'default'=>new RawSql('CURRENT_TIMESTAMP')],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addKey('student_id');
|
||||
$this->forge->addKey('family_id');
|
||||
$this->forge->addKey('template_key');
|
||||
$this->forge->addForeignKey('family_id','families','id','SET NULL','CASCADE','fk_comm_family');
|
||||
|
||||
$this->forge->createTable('communication_logs', true, [
|
||||
'ENGINE'=>'InnoDB','DEFAULT CHARSET'=>'utf8mb4','COLLATE'=>'utf8mb4_unicode_ci',
|
||||
]);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->forge->dropTable('communication_logs', true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
// app/Database/Migrations/2025-09-10-031050_CreateFamilyGuardians.php
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class CreateFamilyGuardians extends Migration
|
||||
{
|
||||
protected $DBGroup = 'default';
|
||||
|
||||
public function up()
|
||||
{
|
||||
$dbName = $this->db->getDatabase();
|
||||
|
||||
// Find exact table names (handles Users/Families casing)
|
||||
$usersRow = $this->db->query(
|
||||
"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA = ? AND LOWER(TABLE_NAME) = 'users' LIMIT 1",
|
||||
[$dbName]
|
||||
)->getFirstRow();
|
||||
$familiesRow = $this->db->query(
|
||||
"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA = ? AND LOWER(TABLE_NAME) = 'families' LIMIT 1",
|
||||
[$dbName]
|
||||
)->getFirstRow();
|
||||
|
||||
if (!$usersRow || !$familiesRow) {
|
||||
throw new \RuntimeException("Required tables not found: users or families in {$dbName}.");
|
||||
}
|
||||
$usersTable = $usersRow->TABLE_NAME;
|
||||
$familiesTable = $familiesRow->TABLE_NAME;
|
||||
|
||||
// Make sure parents are InnoDB (required for FKs)
|
||||
foreach ([$usersTable, $familiesTable] as $t) {
|
||||
$eng = $this->db->query(
|
||||
"SELECT ENGINE FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA=? AND TABLE_NAME=?",
|
||||
[$dbName, $t]
|
||||
)->getFirstRow();
|
||||
if (!$eng || strcasecmp($eng->ENGINE ?? '', 'InnoDB') !== 0) {
|
||||
$this->db->query("ALTER TABLE `{$t}` ENGINE=InnoDB");
|
||||
}
|
||||
}
|
||||
|
||||
// Match child column types to parent id types exactly
|
||||
$usersIdType = $this->db->query(
|
||||
"SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA=? AND TABLE_NAME=? AND COLUMN_NAME='id' LIMIT 1",
|
||||
[$dbName, $usersTable]
|
||||
)->getFirstRow()->COLUMN_TYPE ?? null;
|
||||
|
||||
$familiesIdType = $this->db->query(
|
||||
"SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA=? AND TABLE_NAME=? AND COLUMN_NAME='id' LIMIT 1",
|
||||
[$dbName, $familiesTable]
|
||||
)->getFirstRow()->COLUMN_TYPE ?? null;
|
||||
|
||||
if (!$usersIdType || !$familiesIdType) {
|
||||
throw new \RuntimeException("Could not read id types from {$usersTable} / {$familiesTable}.");
|
||||
}
|
||||
|
||||
// Clean slate in case a broken table exists
|
||||
$this->db->query("DROP TABLE IF EXISTS `family_guardians`");
|
||||
|
||||
// Create with perfectly matching FK column types
|
||||
$sql = "
|
||||
CREATE TABLE `family_guardians` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`family_id` {$familiesIdType} NOT NULL,
|
||||
`user_id` {$usersIdType} NOT NULL,
|
||||
`relation` VARCHAR(32) DEFAULT NULL,
|
||||
`is_primary` TINYINT(1) DEFAULT 0,
|
||||
`receive_emails` TINYINT(1) DEFAULT 1,
|
||||
`receive_sms` TINYINT(1) DEFAULT 0,
|
||||
`custody_notes` VARCHAR(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_family_user` (`family_id`,`user_id`),
|
||||
KEY `idx_fg_family` (`family_id`),
|
||||
KEY `idx_fg_user` (`user_id`),
|
||||
CONSTRAINT `fk_fg_family`
|
||||
FOREIGN KEY (`family_id`) REFERENCES `{$familiesTable}` (`id`)
|
||||
ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `fk_fg_user`
|
||||
FOREIGN KEY (`user_id`) REFERENCES `{$usersTable}` (`id`)
|
||||
ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB
|
||||
DEFAULT CHARSET=utf8mb4
|
||||
COLLATE=utf8mb4_unicode_ci;
|
||||
";
|
||||
$this->db->query($sql);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->db->query("DROP TABLE IF EXISTS `family_guardians`");
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user