82 lines
3.2 KiB
PHP
82 lines
3.2 KiB
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
|
|
{
|
|
/**
|
|
* 1) addresses per user (supports billing/shipping/home/work/etc.)
|
|
* optional link to `locations` for normalized/geocoded data.
|
|
*/
|
|
Schema::create('user_addresses', function (Blueprint $table) {
|
|
$table->bigIncrements('id');
|
|
|
|
// users.id is char(26)
|
|
$table->char('user_id', 26);
|
|
$table->string('label', 100)->nullable(); // "Home", "Office"
|
|
$table->string('kind', 20)->nullable(); // "home", "work", etc
|
|
|
|
// raw, user-entered fields
|
|
$table->string('line1', 255)->nullable();
|
|
$table->string('line2', 255)->nullable();
|
|
$table->string('city', 100)->nullable();
|
|
$table->string('state', 64)->nullable();
|
|
$table->string('postal', 32)->nullable();
|
|
$table->string('country', 64)->nullable();
|
|
|
|
// optional normalized location
|
|
$table->unsignedBigInteger('location_id')->nullable();
|
|
|
|
// nullable so unique index allows many NULLs (only 1 with value 1)
|
|
$table->boolean('is_primary')->nullable()->default(null);
|
|
|
|
// flag for whether this is the user's billing address
|
|
$table->boolean('is_billing')->default(false);
|
|
|
|
$table->timestamps();
|
|
|
|
// helpful indexes
|
|
$table->index(['user_id', 'kind']);
|
|
$table->index('postal');
|
|
$table->index(['user_id', 'is_billing']);
|
|
$table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();
|
|
$table->foreign('location_id')->references('id')->on('locations')->nullOnDelete();
|
|
|
|
// enforce at most one primary per (user,kind)
|
|
$table->unique(['user_id', 'kind', 'is_primary'], 'user_kind_primary_unique');
|
|
});
|
|
|
|
/**
|
|
* 2) lightweight geocoder bias on users (postal/country + optional centroid).
|
|
*/
|
|
Schema::table('users', function (Blueprint $table) {
|
|
$table->string('postal', 32)->nullable()->after('timezone');
|
|
$table->string('country', 64)->nullable()->after('postal');
|
|
$table->decimal('lat', 9, 6)->nullable()->after('country');
|
|
$table->decimal('lon', 9, 6)->nullable()->after('lat');
|
|
$table->index('postal');
|
|
});
|
|
}
|
|
|
|
public function down(): void
|
|
{
|
|
Schema::table('users', function (Blueprint $table) {
|
|
if (Schema::hasColumn('users', 'postal')) $table->dropIndex(['postal']);
|
|
foreach (['postal','country','lat','lon'] as $col) {
|
|
if (Schema::hasColumn('users', $col)) $table->dropColumn($col);
|
|
}
|
|
});
|
|
|
|
Schema::table('user_addresses', function (Blueprint $table) {
|
|
if (Schema::hasColumn('user_addresses', 'user_id')) $table->dropForeign(['user_id']);
|
|
if (Schema::hasColumn('user_addresses', 'location_id')) $table->dropForeign(['location_id']);
|
|
});
|
|
|
|
Schema::dropIfExists('user_addresses');
|
|
}
|
|
};
|