File: /home/xedaptot/rms.naniguide.com/database/migrations/2026_06_07_000001_create_rms_tables.php
<?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('hotels', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('code')->unique();
$table->string('city')->nullable();
$table->string('currency', 3)->default('USD');
$table->integer('total_rooms')->default(0);
$table->decimal('gross_profit_margin', 5, 2)->default(35);
$table->timestamps();
});
Schema::create('room_types', function (Blueprint $table) {
$table->id();
$table->foreignId('hotel_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->string('code');
$table->integer('room_count');
$table->decimal('base_rate', 12, 2);
$table->decimal('min_rate', 12, 2);
$table->decimal('max_rate', 12, 2);
$table->timestamps();
$table->unique(['hotel_id', 'code']);
});
Schema::create('reservations', function (Blueprint $table) {
$table->id();
$table->foreignId('hotel_id')->constrained()->cascadeOnDelete();
$table->foreignId('room_type_id')->constrained()->cascadeOnDelete();
$table->date('stay_date');
$table->integer('rooms_sold');
$table->decimal('room_revenue', 12, 2);
$table->decimal('total_revenue', 12, 2);
$table->string('market_segment')->default('Transient');
$table->date('booked_at')->nullable();
$table->timestamps();
});
Schema::create('forecasts', function (Blueprint $table) {
$table->id();
$table->foreignId('hotel_id')->constrained()->cascadeOnDelete();
$table->date('period_start');
$table->date('period_end');
$table->string('granularity')->default('daily');
$table->decimal('occupancy_forecast', 6, 2);
$table->decimal('adr_forecast', 12, 2);
$table->decimal('revenue_forecast', 12, 2);
$table->decimal('accuracy', 6, 2)->nullable();
$table->timestamps();
});
Schema::create('pricing_rules', function (Blueprint $table) {
$table->id();
$table->foreignId('hotel_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->decimal('occupancy_min', 6, 2)->nullable();
$table->decimal('occupancy_max', 6, 2)->nullable();
$table->integer('pickup_min')->nullable();
$table->integer('booking_window_min')->nullable();
$table->integer('booking_window_max')->nullable();
$table->string('day_of_week')->nullable();
$table->string('season')->nullable();
$table->decimal('adjustment_percent', 6, 2);
$table->boolean('active')->default(true);
$table->timestamps();
});
Schema::create('competitors', function (Blueprint $table) {
$table->id();
$table->foreignId('hotel_id')->constrained()->cascadeOnDelete();
$table->string('name');
$table->date('rate_date');
$table->decimal('competitor_rate', 12, 2);
$table->string('room_type')->nullable();
$table->timestamps();
});
Schema::create('reports', function (Blueprint $table) {
$table->id();
$table->foreignId('hotel_id')->constrained()->cascadeOnDelete();
$table->string('type');
$table->date('period_start');
$table->date('period_end');
$table->json('payload');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('reports');
Schema::dropIfExists('competitors');
Schema::dropIfExists('pricing_rules');
Schema::dropIfExists('forecasts');
Schema::dropIfExists('reservations');
Schema::dropIfExists('room_types');
Schema::dropIfExists('hotels');
}
};