First Commit

This commit is contained in:
marco
2026-09-01 07:49:48 -03:00
commit 28b1044038
399 changed files with 41659 additions and 0 deletions
@@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('sessions');
}
};
@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->primary();
$table->mediumText('value');
$table->bigInteger('expiration')->index();
});
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary();
$table->string('owner');
$table->bigInteger('expiration')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cache');
Schema::dropIfExists('cache_locks');
}
};
@@ -0,0 +1,59 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('jobs', function (Blueprint $table) {
$table->id();
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedSmallInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
Schema::create('job_batches', function (Blueprint $table) {
$table->string('id')->primary();
$table->string('name');
$table->integer('total_jobs');
$table->integer('pending_jobs');
$table->integer('failed_jobs');
$table->longText('failed_job_ids');
$table->mediumText('options')->nullable();
$table->integer('cancelled_at')->nullable();
$table->integer('created_at');
$table->integer('finished_at')->nullable();
});
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->string('connection');
$table->string('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
$table->index(['connection', 'queue', 'failed_at']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('jobs');
Schema::dropIfExists('job_batches');
Schema::dropIfExists('failed_jobs');
}
};
@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->text('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable()->index();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};
@@ -0,0 +1,137 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$teams = config('permission.teams');
$tableNames = config('permission.table_names');
$columnNames = config('permission.column_names');
$pivotRole = $columnNames['role_pivot_key'] ?? 'role_id';
$pivotPermission = $columnNames['permission_pivot_key'] ?? 'permission_id';
throw_if(empty($tableNames), 'Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.');
throw_if($teams && empty($columnNames['team_foreign_key'] ?? null), 'Error: team_foreign_key on config/permission.php not loaded. Run [php artisan config:clear] and try again.');
/**
* See `docs/prerequisites.md` for suggested lengths on 'name' and 'guard_name' if "1071 Specified key was too long" errors are encountered.
*/
Schema::create($tableNames['permissions'], static function (Blueprint $table) {
$table->id(); // permission id
$table->string('name');
$table->string('guard_name');
$table->timestamps();
$table->unique(['name', 'guard_name']);
});
/**
* See `docs/prerequisites.md` for suggested lengths on 'name' and 'guard_name' if "1071 Specified key was too long" errors are encountered.
*/
Schema::create($tableNames['roles'], static function (Blueprint $table) use ($teams, $columnNames) {
$table->id(); // role id
if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing
$table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable();
$table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');
}
$table->string('name');
$table->string('guard_name');
$table->timestamps();
if ($teams || config('permission.testing')) {
$table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);
} else {
$table->unique(['name', 'guard_name']);
}
});
Schema::create($tableNames['model_has_permissions'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) {
$table->unsignedBigInteger($pivotPermission);
$table->string('model_type');
$table->unsignedBigInteger($columnNames['model_morph_key']);
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
$table->foreign($pivotPermission)
->references('id') // permission id
->on($tableNames['permissions'])
->cascadeOnDelete();
if ($teams) {
$table->unsignedBigInteger($columnNames['team_foreign_key']);
$table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');
$table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'],
'model_has_permissions_permission_model_type_primary');
} else {
$table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
'model_has_permissions_permission_model_type_primary');
}
});
Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) {
$table->unsignedBigInteger($pivotRole);
$table->string('model_type');
$table->unsignedBigInteger($columnNames['model_morph_key']);
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
$table->foreign($pivotRole)
->references('id') // role id
->on($tableNames['roles'])
->cascadeOnDelete();
if ($teams) {
$table->unsignedBigInteger($columnNames['team_foreign_key']);
$table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');
$table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'],
'model_has_roles_role_model_type_primary');
} else {
$table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'],
'model_has_roles_role_model_type_primary');
}
});
Schema::create($tableNames['role_has_permissions'], static function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) {
$table->unsignedBigInteger($pivotPermission);
$table->unsignedBigInteger($pivotRole);
$table->foreign($pivotPermission)
->references('id') // permission id
->on($tableNames['permissions'])
->cascadeOnDelete();
$table->foreign($pivotRole)
->references('id') // role id
->on($tableNames['roles'])
->cascadeOnDelete();
$table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary');
});
app('cache')
->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
->forget(config('permission.cache.key'));
}
/**
* Reverse the migrations.
*/
public function down(): void
{
$tableNames = config('permission.table_names');
throw_if(empty($tableNames), 'Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
Schema::dropIfExists($tableNames['role_has_permissions']);
Schema::dropIfExists($tableNames['model_has_roles']);
Schema::dropIfExists($tableNames['model_has_permissions']);
Schema::dropIfExists($tableNames['roles']);
Schema::dropIfExists($tableNames['permissions']);
}
};
@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('subjects', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
$table->string('name');
$table->text('description')->nullable();
$table->text('introduction')->nullable();
$table->boolean('is_system')->default(false);
$table->boolean('is_active')->default(true);
$table->timestamps();
$table->index(['user_id', 'is_system']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('subjects');
}
};
@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('user_subjects', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->foreignId('subject_id')->constrained()->cascadeOnDelete();
$table->boolean('is_active')->default(true);
$table->integer('frequency_days')->default(7);
$table->time('preferred_time')->nullable();
$table->json('weekdays')->nullable();
$table->timestamps();
$table->unique(['user_id', 'subject_id']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('user_subjects');
}
};
@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('insights', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->foreignId('subject_id')->constrained()->cascadeOnDelete();
$table->text('content');
$table->string('type')->default('insight');
$table->json('metadata')->nullable();
$table->integer('input_tokens')->default(0);
$table->integer('output_tokens')->default(0);
$table->timestamp('sent_at')->nullable();
$table->timestamps();
$table->index(['user_id', 'subject_id', 'created_at']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('insights');
}
};
@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('insight_schedules', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->foreignId('subject_id')->constrained()->cascadeOnDelete();
$table->string('frequency')->default('weekly');
$table->json('weekdays')->nullable();
$table->time('preferred_time')->nullable();
$table->boolean('is_active')->default(true);
$table->timestamp('last_sent_at')->nullable();
$table->timestamps();
$table->unique(['user_id', 'subject_id']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('insight_schedules');
}
};
@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('telegram_users', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('telegram_user_id')->unique();
$table->string('username')->nullable();
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
$table->boolean('is_active')->default(true);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('telegram_users');
}
};
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('token_usages', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->unsignedInteger('input_tokens')->default(0);
$table->unsignedInteger('output_tokens')->default(0);
$table->unsignedInteger('total_tokens')->default(0);
$table->string('model')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('token_usages');
}
};
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('phone')->nullable()->after('email');
$table->string('locale')->default('pt_BR')->after('phone');
$table->boolean('is_active')->default(true)->after('locale');
$table->boolean('is_approved')->default(false)->after('is_active');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn(['phone', 'locale', 'is_active', 'is_approved']);
});
}
};
@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('user_consents', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('terms_version');
$table->string('privacy_version');
$table->string('cookie_version');
$table->timestamp('accepted_at');
$table->string('ip_address')->nullable();
$table->text('user_agent')->nullable();
$table->timestamps();
$table->index(['user_id', 'accepted_at']);
});
}
public function down(): void
{
Schema::dropIfExists('user_consents');
}
};
@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Migration to rename frequency_days to frequency in user_subjects table.
* This ensures consistency between the model and the controller.
*/
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
if (Schema::hasColumn('user_subjects', 'frequency_days')) {
$table->renameColumn('frequency_days', 'frequency');
}
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
if (Schema::hasColumn('user_subjects', 'frequency')) {
$table->renameColumn('frequency', 'frequency_days');
}
});
}
};
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Migration to change the frequency column type from integer to string.
* This allows storing frequency values like 'daily', 'weekly', 'biweekly', 'monthly'.
*/
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
$table->string('frequency', 50)->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
$table->integer('frequency')->change();
});
}
};
@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Migration to change preferred_time from single time to JSON array of times.
* This allows users to set multiple delivery times per subject.
*/
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
$table->json('preferred_times')->nullable()->after('frequency');
});
// Migrate existing data: convert single preferred_time to JSON array
DB::table('user_subjects')->whereNotNull('preferred_time')->update([
'preferred_times' => DB::raw("JSON_ARRAY(preferred_time)"),
]);
Schema::table('user_subjects', function (Blueprint $table) {
$table->dropColumn('preferred_time');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
$table->time('preferred_time')->nullable()->after('frequency');
});
// Restore data: convert first element of JSON array back to single time
DB::statement("UPDATE user_subjects SET preferred_time = JSON_UNQUOTE(JSON_EXTRACT(preferred_times, '$[0]')) WHERE preferred_times IS NOT NULL");
Schema::table('user_subjects', function (Blueprint $table) {
$table->dropColumn('preferred_times');
});
}
};
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Migration to add bot_token and bot_username fields to telegram_users table.
* This allows each user to configure their own Telegram bot.
*/
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('telegram_users', function (Blueprint $table) {
$table->string('bot_token')->nullable()->after('telegram_user_id');
$table->string('bot_username')->nullable()->after('bot_token');
$table->string('chat_id')->nullable()->after('bot_username');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('telegram_users', function (Blueprint $table) {
$table->dropColumn(['bot_token', 'bot_username', 'chat_id']);
});
}
};
@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Migration to rename username column to telegram_username in telegram_users table.
* Ensures consistency with the model's fillable attributes.
*/
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('telegram_users', function (Blueprint $table) {
$table->renameColumn('username', 'telegram_username');
$table->renameColumn('first_name', 'telegram_first_name');
$table->renameColumn('last_name', 'telegram_last_name');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('telegram_users', function (Blueprint $table) {
$table->renameColumn('telegram_username', 'username');
$table->renameColumn('telegram_first_name', 'first_name');
$table->renameColumn('telegram_last_name', 'last_name');
});
}
};
@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Migration to add provider column to token_usages table.
*/
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('token_usages', function (Blueprint $table) {
if (!Schema::hasColumn('token_usages', 'provider')) {
$table->string('provider', 50)->nullable()->after('model');
}
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('token_usages', function (Blueprint $table) {
if (Schema::hasColumn('token_usages', 'provider')) {
$table->dropColumn('provider');
}
});
}
};
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Migration to add language field to user_subjects table.
* Allows users to choose the language for AI-generated insights per subject.
*/
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
$table->string('insight_language', 10)->nullable()->after('weekdays');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
$table->dropColumn('insight_language');
});
}
};
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Migration to add delivery_channels field to user_subjects table.
* Allows users to choose where to receive insights (dashboard, telegram, etc.).
*/
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
$table->json('delivery_channels')->nullable()->after('insight_language');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
$table->dropColumn('delivery_channels');
});
}
};
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Migration to add last_sent_at column to user_subjects table.
* Tracks when the last insight was sent for scheduling purposes.
*/
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
$table->timestamp('last_sent_at')->nullable()->after('delivery_channels');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('user_subjects', function (Blueprint $table) {
$table->dropColumn('last_sent_at');
});
}
};
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Migration to add token_limit field to users table.
* SuperAdmin can set the maximum token usage per user.
*/
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->bigInteger('token_limit')->nullable()->after('is_approved');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('token_limit');
});
}
};
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Migration to add timezone field to users table.
* Allows users to set their local timezone for scheduling insights.
*/
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('timezone', 50)->nullable()->after('locale');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('timezone');
});
}
};
@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('subscription_plans', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description')->nullable();
$table->decimal('price', 10, 2);
$table->string('currency', 3)->default('BRL');
$table->integer('duration_days')->default(30);
$table->integer('token_limit')->nullable();
$table->boolean('is_active')->default(true);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('subscription_plans');
}
};
@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('user_subscriptions', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->foreignId('subscription_plan_id')->constrained()->cascadeOnDelete();
$table->timestamp('start_date');
$table->timestamp('end_date');
$table->string('status')->default('active'); // active, expired, cancelled, suspended
$table->boolean('payment_approved')->default(false);
$table->timestamp('cancelled_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('user_subscriptions');
}
};
@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('invoices', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->foreignId('user_subscription_id')->constrained()->cascadeOnDelete();
$table->string('invoice_number')->unique();
$table->decimal('amount', 10, 2);
$table->string('currency', 3)->default('BRL');
$table->string('status')->default('pending'); // pending, paid, cancelled, refunded
$table->string('payment_method')->nullable();
$table->timestamp('paid_at')->nullable();
$table->string('pdf_path')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('invoices');
}
};
@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('user_notifications', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('type'); // payment_due, payment_overdue, subscription_expiring, subscription_expired, payment_received, admin_message
$table->string('title');
$table->text('message')->nullable();
$table->boolean('is_read')->default(false);
$table->timestamp('read_at')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('user_notifications');
}
};
@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('telegram_users', function (Blueprint $table) {
$table->dropUnique('telegram_users_telegram_user_id_unique');
});
}
public function down(): void
{
Schema::table('telegram_users', function (Blueprint $table) {
$table->unique('telegram_user_id');
});
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('subjects', function (Blueprint $table) {
$table->string('message_type')->nullable()->after('introduction');
$table->text('custom_instructions')->nullable()->after('message_type');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('subjects', function (Blueprint $table) {
$table->dropColumn(['message_type', 'custom_instructions']);
});
}
};
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('user_interests', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('interest');
$table->timestamps();
$table->index('user_id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('user_interests');
}
};
@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('chat_messages', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->text('message');
$table->text('response')->nullable();
$table->string('provider')->nullable();
$table->string('model')->nullable();
$table->integer('input_tokens')->default(0);
$table->integer('output_tokens')->default(0);
$table->timestamp('sent_at')->nullable();
$table->timestamps();
$table->index(['user_id', 'created_at']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('chat_messages');
}
};
@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('settings', function (Blueprint $table) {
$table->id();
$table->string('key')->unique();
$table->text('value')->nullable();
$table->string('type')->default('string');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('settings');
}
};
@@ -0,0 +1,53 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('custom_subjects', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->string('pdf_path');
$table->text('extracted_content')->nullable();
$table->string('processing_status')->default('pending');
$table->text('error_message')->nullable();
$table->boolean('is_active')->default(true);
$table->timestamps();
$table->index(['user_id', 'is_active']);
});
Schema::create('custom_subject_questions', function (Blueprint $table) {
$table->id();
$table->foreignId('custom_subject_id')->constrained()->cascadeOnDelete();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->text('question');
$table->text('answer')->nullable();
$table->string('provider')->nullable();
$table->string('model')->nullable();
$table->integer('input_tokens')->default(0);
$table->integer('output_tokens')->default(0);
$table->timestamp('asked_at');
$table->timestamps();
$table->index(['custom_subject_id', 'created_at']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('custom_subject_questions');
Schema::dropIfExists('custom_subjects');
}
};