recreate project
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class CreateInventoryTables extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
// --------- inventory_categories ----------
|
||||
$this->forge->addField([
|
||||
'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
|
||||
'type' => ['type' => 'ENUM("classroom","book","office","kitchen")', 'null' => false, 'default' => 'office'],
|
||||
'name' => ['type' => 'VARCHAR', 'constraint' => 120, 'null' => false],
|
||||
'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(['type', 'name']); // unique per type
|
||||
$this->forge->createTable('inventory_categories', true, [
|
||||
'ENGINE' => 'InnoDB',
|
||||
]);
|
||||
|
||||
// --------- inventory_items ----------
|
||||
$this->forge->addField([
|
||||
'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
|
||||
'type' => ['type' => 'ENUM("classroom","book","office","kitchen")', 'null' => false],
|
||||
'category_id' => ['type' => 'INT', 'unsigned' => true, 'null' => true],
|
||||
|
||||
'name' => ['type' => 'VARCHAR', 'constraint' => 190, 'null' => false],
|
||||
'description' => ['type' => 'TEXT', 'null' => true],
|
||||
|
||||
'quantity' => ['type' => 'INT', 'unsigned' => true, 'default' => 0],
|
||||
'unit' => ['type' => 'VARCHAR', 'constraint' => 32, 'null' => true, 'default' => null],
|
||||
|
||||
// Classroom-only condition
|
||||
'condition' => ['type' => 'ENUM("good","needs_repair","need_replace","cannot_find")', 'null' => true, 'default' => null],
|
||||
|
||||
// Book extras (author removed earlier)
|
||||
'isbn' => ['type' => 'VARCHAR', 'constraint' => 32, 'null' => true],
|
||||
'edition' => ['type' => 'VARCHAR', 'constraint' => 32, 'null' => true],
|
||||
|
||||
// Misc
|
||||
'sku' => ['type' => 'VARCHAR', 'constraint' => 64, 'null' => true],
|
||||
'notes' => ['type' => 'TEXT', 'null' => true],
|
||||
|
||||
// Academic tagging
|
||||
'semester' => ['type' => 'ENUM("Spring","Fall")', 'null' => true],
|
||||
'school_year' => ['type' => 'VARCHAR', 'constraint' => 16, 'null' => true], // e.g. 2025-2026
|
||||
|
||||
// Audit
|
||||
'updated_by' => ['type' => 'INT', 'unsigned' => true, 'null' => true],
|
||||
|
||||
'created_at' => ['type' => 'DATETIME', 'null' => true],
|
||||
'updated_at' => ['type' => 'DATETIME', 'null' => true],
|
||||
]);
|
||||
|
||||
// Indexes
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addKey(['type', 'name']);
|
||||
$this->forge->addKey(['school_year', 'semester']);
|
||||
$this->forge->addKey('category_id'); // ensure indexed for FK
|
||||
$this->forge->addKey('updated_by'); // ensure indexed for FK
|
||||
|
||||
// Category FK (safe; category table we just created with InnoDB)
|
||||
$this->forge->addForeignKey('category_id', 'inventory_categories', 'id', 'SET NULL', 'CASCADE');
|
||||
|
||||
// Create items table first, then add users FK conditionally
|
||||
$this->forge->createTable('inventory_items', true, [
|
||||
'ENGINE' => 'InnoDB',
|
||||
]);
|
||||
|
||||
// ---- Add updated_by → users(id) FK conditionally & safely ----
|
||||
$db = \Config\Database::connect();
|
||||
|
||||
if ($db->tableExists('users')) {
|
||||
// Confirm users is InnoDB and id is an unsigned INT
|
||||
$engineRow = $db->query("
|
||||
SELECT ENGINE FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users'
|
||||
")->getFirstRow('array');
|
||||
|
||||
$colRow = $db->query("
|
||||
SELECT COLUMN_TYPE, IS_NULLABLE
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'users' AND COLUMN_NAME = 'id'
|
||||
")->getFirstRow('array');
|
||||
|
||||
$isInno = isset($engineRow['ENGINE']) && strtoupper($engineRow['ENGINE']) === 'INNODB';
|
||||
$isUint = isset($colRow['COLUMN_TYPE']) && stripos($colRow['COLUMN_TYPE'], 'int') !== false && stripos($colRow['COLUMN_TYPE'], 'unsigned') !== false;
|
||||
|
||||
if ($isInno && $isUint) {
|
||||
// Add the FK now (separate ALTER avoids "incorrectly formed" during CREATE)
|
||||
$db->query("
|
||||
ALTER TABLE inventory_items
|
||||
ADD CONSTRAINT fk_inventory_items_updated_by
|
||||
FOREIGN KEY (updated_by) REFERENCES users(id)
|
||||
ON DELETE SET NULL ON UPDATE CASCADE
|
||||
");
|
||||
}
|
||||
// If not compatible, we skip the FK to avoid migration failure.
|
||||
}
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
// Drop children first
|
||||
$db = \Config\Database::connect();
|
||||
if ($db->tableExists('inventory_items')) {
|
||||
// drop conditional FK if exists
|
||||
try { $db->query("ALTER TABLE inventory_items DROP FOREIGN KEY fk_inventory_items_updated_by"); } catch (\Throwable $e) {}
|
||||
}
|
||||
|
||||
$this->forge->dropTable('inventory_items', true);
|
||||
$this->forge->dropTable('inventory_categories', true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user