forge->addField([ 'id' => ['type'=>'INT','unsigned'=>true,'auto_increment'=>true], 'item_id' => ['type'=>'INT','unsigned'=>true,'null'=>false], 'qty_change' => ['type'=>'INT','null'=>false], // +in / -out 'movement_type' => ['type'=>'ENUM("initial","in","out","adjust","distribution")','null'=>false,'default'=>'adjust'], 'reason' => ['type'=>'VARCHAR','constraint'=>120,'null'=>true], 'note' => ['type'=>'TEXT','null'=>true], // tagging 'semester' => ['type'=>'ENUM("Spring","Fall")','null'=>true], 'school_year' => ['type'=>'VARCHAR','constraint'=>16,'null'=>true], // e.g. 2025-2026 // who/for whom 'performed_by' => ['type'=>'INT','unsigned'=>true,'null'=>true], // user id 'teacher_id' => ['type'=>'INT','unsigned'=>true,'null'=>true], 'student_id' => ['type'=>'INT','unsigned'=>true,'null'=>true], 'class_section_id'=> ['type'=>'INT','unsigned'=>true,'null'=>true], 'created_at' => ['type'=>'DATETIME','null'=>true], 'updated_at' => ['type'=>'DATETIME','null'=>true], ]); $this->forge->addKey('id', true); $this->forge->addKey('item_id'); $this->forge->addKey(['school_year','semester']); $this->forge->addKey('movement_type'); $this->forge->addForeignKey('item_id', 'inventory_items', 'id', 'CASCADE', 'CASCADE'); // Create table as InnoDB $this->forge->createTable('inventory_movements', true, ['ENGINE'=>'InnoDB']); // Optional FKs to users if compatible $db = \Config\Database::connect(); if ($db->tableExists('users')) { // try add FK; ignore failures (engine/type mismatch) try { $db->query("ALTER TABLE inventory_movements ADD CONSTRAINT fk_inv_mov_performed_by FOREIGN KEY (performed_by) REFERENCES users(id) ON DELETE SET NULL ON UPDATE CASCADE"); } catch (\Throwable $e) {} try { $db->query("ALTER TABLE inventory_movements ADD CONSTRAINT fk_inv_mov_teacher FOREIGN KEY (teacher_id) REFERENCES users(id) ON DELETE SET NULL ON UPDATE CASCADE"); } catch (\Throwable $e) {} } } public function down() { $this->forge->dropTable('inventory_movements', true); } }