diff --git a/app/RSpade/Commands/Migrate/Migrate_Begin_Command.php b/app/RSpade/Commands/Migrate/Migrate_Begin_Command.php index ba2e8872c..1dd5e0eba 100755 --- a/app/RSpade/Commands/Migrate/Migrate_Begin_Command.php +++ b/app/RSpade/Commands/Migrate/Migrate_Begin_Command.php @@ -67,7 +67,7 @@ class Migrate_Begin_Command extends Command try { // Step 1: Stop MySQL using supervisorctl - $this->info('1️⃣ Stopping MySQL server...'); + $this->info('[1] Stopping MySQL server...'); shell_exec('supervisorctl stop mysql 2>&1'); // Wait a moment for process to die @@ -75,24 +75,24 @@ class Migrate_Begin_Command extends Command // Step 2: Remove old backup if exists if (is_dir($this->backup_dir)) { - $this->info('2️⃣ Removing old backup...'); + $this->info('[2] Removing old backup...'); $this->run_command(['rm', '-rf', $this->backup_dir]); } // Step 3: Copy MySQL data directory - $this->info('3️⃣ Creating snapshot of MySQL data...'); + $this->info('[3] Creating snapshot of MySQL data...'); $this->run_command(['cp', '-r', $this->mysql_data_dir, $this->backup_dir]); // Step 4: Start MySQL again using supervisorctl - $this->info('4️⃣ Starting MySQL server...'); + $this->info('[4] Starting MySQL server...'); shell_exec('supervisorctl start mysql 2>&1'); // Step 5: Wait for MySQL to be ready - $this->info('5️⃣ Waiting for MySQL to be ready...'); + $this->info('[5] Waiting for MySQL to be ready...'); $this->wait_for_mysql_ready(); // Step 6: Create migration flag file - $this->info('6️⃣ Creating migration flag...'); + $this->info('[6] Creating migration flag...'); file_put_contents($this->flag_file, json_encode([ 'started_at' => now()->toIso8601String(), 'started_by' => get_current_user(), diff --git a/app/RSpade/Commands/Migrate/Migrate_Commit_Command.php b/app/RSpade/Commands/Migrate/Migrate_Commit_Command.php index 3038b5466..62252e8f2 100755 --- a/app/RSpade/Commands/Migrate/Migrate_Commit_Command.php +++ b/app/RSpade/Commands/Migrate/Migrate_Commit_Command.php @@ -87,12 +87,12 @@ class Migrate_Commit_Command extends Command try { // Step 1: Remove backup directory if (is_dir($this->backup_dir)) { - $this->info('1️⃣ Removing backup snapshot...'); + $this->info('[1] Removing backup snapshot...'); $this->run_command(['rm', '-rf', $this->backup_dir]); } // Step 2: Remove migration flag - $this->info('2️⃣ Removing migration flag...'); + $this->info('[2] Removing migration flag...'); unlink($this->flag_file); // Success diff --git a/app/RSpade/Commands/Migrate/Migrate_Rollback_Command.php b/app/RSpade/Commands/Migrate/Migrate_Rollback_Command.php index 5ab9b7693..701e375eb 100755 --- a/app/RSpade/Commands/Migrate/Migrate_Rollback_Command.php +++ b/app/RSpade/Commands/Migrate/Migrate_Rollback_Command.php @@ -41,37 +41,37 @@ class Migrate_Rollback_Command extends Command try { // Step 1: Stop MySQL using supervisorctl - $this->info('1️⃣ Stopping MySQL server...'); + $this->info('[1] Stopping MySQL server...'); shell_exec('supervisorctl stop mysql 2>&1'); // Wait a moment for process to die sleep(3); // Step 2: Clear current MySQL data - $this->info('2️⃣ Clearing current database data...'); + $this->info('[2] Clearing current database data...'); // Use shell_exec to clear directory contents instead of removing directory shell_exec("rm -rf {$this->mysql_data_dir}/* 2>/dev/null"); shell_exec("rm -rf {$this->mysql_data_dir}/.* 2>/dev/null"); // Step 3: Restore backup - $this->info('3️⃣ Restoring database snapshot...'); + $this->info('[3] Restoring database snapshot...'); shell_exec("cp -r {$this->backup_dir}/* {$this->mysql_data_dir}/"); shell_exec("cp -r {$this->backup_dir}/.[^.]* {$this->mysql_data_dir}/ 2>/dev/null"); // Step 4: Fix permissions (MySQL needs to own the files) - $this->info('4️⃣ Setting correct permissions...'); + $this->info('[4] Setting correct permissions...'); $this->run_command(['chown', '-R', 'mysql:mysql', $this->mysql_data_dir]); // Step 5: Start MySQL using supervisorctl - $this->info('5️⃣ Starting MySQL server...'); + $this->info('[5] Starting MySQL server...'); shell_exec('supervisorctl start mysql 2>&1'); // Step 6: Wait for MySQL to be ready - $this->info('6️⃣ Waiting for MySQL to be ready...'); + $this->info('[6] Waiting for MySQL to be ready...'); $this->wait_for_mysql_ready(); // Step 7: Keep backup and flag - stay in migration mode - $this->info('7️⃣ Rollback complete...'); + $this->info('[7] Rollback complete...'); // Success $this->info(''); diff --git a/app/RSpade/Commands/Rsx/Constants_Regenerate_Command.php b/app/RSpade/Commands/Rsx/Constants_Regenerate_Command.php index 46ed8b759..06282c52d 100755 --- a/app/RSpade/Commands/Rsx/Constants_Regenerate_Command.php +++ b/app/RSpade/Commands/Rsx/Constants_Regenerate_Command.php @@ -132,19 +132,37 @@ class Constants_Regenerate_Command extends Command $columnType = DB::getSchemaBuilder()->getColumnType($table, $column); $validIntegerTypes = ['integer', 'bigint', 'smallint', 'tinyint', 'mediumint']; - if (!in_array($columnType, $validIntegerTypes)) { + // Special case: allow 'boolean' type (TINYINT(1)) ONLY if enum values are 0 and 1 + $isBooleanEnum = false; + if ($columnType === 'boolean') { + $enumKeys = array_keys($enumValues); + sort($enumKeys); + if ($enumKeys === [0, 1]) { + $isBooleanEnum = true; + } + } + + if (!in_array($columnType, $validIntegerTypes) && !$isBooleanEnum) { $this->error("Invalid column type '{$columnType}' for enum column '{$column}' in table '{$table}' (model '{$fullClassName}')."); $this->newLine(); $this->error("ENUM COLUMNS MUST BE INTEGER TYPES."); $this->newLine(); + + // Special message for boolean/TINYINT + if ($columnType === 'boolean') { + $this->line("TINYINT columns are reported as 'boolean' by Laravel because TINYINT is ONLY for true/false values."); + $this->line("For enum values with multiple options (1, 2, 3, etc.), you MUST use INT or BIGINT."); + $this->newLine(); + } + $this->line("Enum values are stored as integers in the database. The column must be defined as an"); - $this->line("integer type (INT, BIGINT, SMALLINT, TINYINT, or MEDIUMINT), not VARCHAR or other string types."); + $this->line("integer type (INT, BIGINT, SMALLINT, or MEDIUMINT), not VARCHAR, TINYINT, or other types."); $this->newLine(); $this->line("Current column type: {$columnType}"); $this->line("Required column types: " . implode(', ', $validIntegerTypes)); $this->newLine(); $this->line("To fix this issue:"); - $this->line("1. Create a migration to change the column type to an integer"); + $this->line("1. Create a migration to change the column type to INT or BIGINT"); $this->line("2. Example migration:"); $this->newLine(); $this->line(" public function up()"); diff --git a/database/migrations/2025_09_16_074547_add_status_to_users_table.php b/database/migrations/2025_09_16_074547_add_status_to_users_table.php index ec018cc4f..883bfdf6c 100755 --- a/database/migrations/2025_09_16_074547_add_status_to_users_table.php +++ b/database/migrations/2025_09_16_074547_add_status_to_users_table.php @@ -19,11 +19,11 @@ return new class extends Migration public function up() { // Add status column (1=active, 2=inactive, 3=suspended) - DB::statement("ALTER TABLE users ADD COLUMN status TINYINT NOT NULL DEFAULT 1 AFTER is_verified"); + DB::statement("ALTER TABLE users ADD COLUMN status INT NOT NULL DEFAULT 1 AFTER is_verified"); DB::statement("ALTER TABLE users ADD INDEX idx_status (status)"); // Add user_role_id column (1=read_only, 2=standard, 3=admin, 4=billing_admin, 5=root_admin) - DB::statement("ALTER TABLE users ADD COLUMN user_role_id TINYINT NOT NULL DEFAULT 2 AFTER status"); + DB::statement("ALTER TABLE users ADD COLUMN user_role_id INT NOT NULL DEFAULT 2 AFTER status"); DB::statement("ALTER TABLE users ADD INDEX idx_user_role_id (user_role_id)"); } diff --git a/database/migrations/2025_09_16_075234_rename_status_column_to_status_id.php b/database/migrations/2025_09_16_075234_rename_status_column_to_status_id.php index bf6eefc0b..00792e003 100755 --- a/database/migrations/2025_09_16_075234_rename_status_column_to_status_id.php +++ b/database/migrations/2025_09_16_075234_rename_status_column_to_status_id.php @@ -19,7 +19,7 @@ return new class extends Migration public function up() { // Rename status column to status_id to match enum naming convention - DB::statement("ALTER TABLE users CHANGE COLUMN status status_id TINYINT NOT NULL DEFAULT 1"); + DB::statement("ALTER TABLE users CHANGE COLUMN status status_id INT NOT NULL DEFAULT 1"); // Recreate the index with the new column name DB::statement("ALTER TABLE users DROP INDEX idx_status"); diff --git a/database/migrations/2025_09_16_075915_create_demo_products_table.php b/database/migrations/2025_09_16_075915_create_demo_products_table.php index b672947fb..d4d9ffb1c 100755 --- a/database/migrations/2025_09_16_075915_create_demo_products_table.php +++ b/database/migrations/2025_09_16_075915_create_demo_products_table.php @@ -31,8 +31,8 @@ return new class extends Migration name VARCHAR(255) NOT NULL, description TEXT, price DECIMAL(10,2) NOT NULL, - status_id TINYINT NOT NULL DEFAULT 1, - category_id TINYINT NOT NULL DEFAULT 1, + status_id INT NOT NULL DEFAULT 1, + category_id INT NOT NULL DEFAULT 1, created_at TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3), updated_at TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), INDEX idx_status_id (status_id),