feat(db): 7 MVP-1 migrations — UUID, tenant_id, role_user UNIQUE(user_id), parent_child no-tenant
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>main
parent
af49f091f5
commit
a198cd1fbe
|
|
@ -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('tenants', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->uuid('uuid')->unique();
|
||||||
|
$table->string('name');
|
||||||
|
$table->enum('type', ['school', 'private', 'system'])->default('private');
|
||||||
|
$table->boolean('active')->default(true);
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('tenants');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -13,12 +13,18 @@ return new class extends Migration
|
||||||
{
|
{
|
||||||
Schema::create('users', function (Blueprint $table) {
|
Schema::create('users', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
|
$table->uuid('uuid')->unique();
|
||||||
|
$table->unsignedBigInteger('tenant_id');
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
$table->string('email')->unique();
|
$table->string('email')->unique();
|
||||||
$table->timestamp('email_verified_at')->nullable();
|
$table->timestamp('email_verified_at')->nullable();
|
||||||
$table->string('password');
|
$table->string('password');
|
||||||
$table->rememberToken();
|
$table->rememberToken();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
|
||||||
|
$table->foreign('tenant_id')->references('id')->on('tenants');
|
||||||
|
$table->index('tenant_id');
|
||||||
});
|
});
|
||||||
|
|
||||||
Schema::create('password_reset_tokens', function (Blueprint $table) {
|
Schema::create('password_reset_tokens', function (Blueprint $table) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?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('roles', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name')->unique();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('roles');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -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('licenses', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->uuid('uuid')->unique();
|
||||||
|
$table->unsignedBigInteger('tenant_id');
|
||||||
|
$table->enum('type', ['per_student', 'school_flat'])->default('per_student');
|
||||||
|
$table->unsignedInteger('seats')->nullable();
|
||||||
|
$table->date('expires_at')->nullable();
|
||||||
|
$table->boolean('active')->default(true);
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
|
||||||
|
$table->foreign('tenant_id')->references('id')->on('tenants');
|
||||||
|
$table->index('tenant_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('licenses');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -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('role_user', function (Blueprint $table) {
|
||||||
|
$table->id(); // AUTO_INCREMENT PK — NOT composite primary key
|
||||||
|
$table->unsignedBigInteger('role_id');
|
||||||
|
$table->unsignedBigInteger('user_id');
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->unique('user_id'); // 1 role per user enforced at DB level
|
||||||
|
$table->foreign('role_id')->references('id')->on('roles')->cascadeOnDelete();
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('role_user');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -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('license_assignments', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->unsignedBigInteger('license_id');
|
||||||
|
$table->unsignedBigInteger('user_id');
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->unique(['license_id', 'user_id']);
|
||||||
|
$table->foreign('license_id')->references('id')->on('licenses')->cascadeOnDelete();
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('license_assignments');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -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('parent_child', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->uuid('uuid')->unique();
|
||||||
|
// NO tenant_id — cross-tenant parent-child allowed (spec Option B)
|
||||||
|
$table->unsignedBigInteger('parent_id');
|
||||||
|
$table->unsignedBigInteger('child_id');
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->unique(['parent_id', 'child_id']);
|
||||||
|
$table->foreign('parent_id')->references('id')->on('users')->cascadeOnDelete();
|
||||||
|
$table->foreign('child_id')->references('id')->on('users')->cascadeOnDelete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('parent_child');
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue