laravel-addresses/database/migrations/create_blax_address_tables....

242 lines
12 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Blax\Addresses\Migrations;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* Creates two tables:
* - `addresses` stores the physical address data (location, coordinates, etc.)
* - `address_links` polymorphic pivot linking addresses to any Eloquent model
*/
public function up(): void
{
/*
|----------------------------------------------------------------------
| addresses — the canonical address record
|----------------------------------------------------------------------
|
| Designed to support worldwide formats, from a GPS point in the
| wilderness to a specific room inside a skyscraper.
|
| Coordinate system:
| latitude / longitude → WGS-84 decimal degrees
| altitude → metres Above Mean Sea Level (AMSL)
|
*/
Schema::create(config('addresses.table_names.addresses', 'addresses'), function (Blueprint $table) {
// UUID PK — the Address model uses `HasUuids`. If you've already
// published a previous version of this stub with `$table->id()`
// (auto-increment), keep that — but you'll need to either drop
// `HasUuids` from your Address override or migrate the column to
// a UUID. Don't change a populated table's PK shape blindly.
$table->uuid('id')->primary();
// ── Street-level addressing ─────────────────────────────
// Primary street line (street name + house/building number).
$table->string('street')->nullable();
// Additional line for c/o, suite, apartment, P.O. box, etc.
$table->string('street_extra')->nullable();
// ── Building / indoor precision ─────────────────────────
// Building or complex name (e.g. "Empire State Building", "Block C").
$table->string('building')->nullable();
// Floor / level inside the building (string to allow "GF", "B2", "Mezzanine").
$table->string('floor')->nullable();
// Room, suite or unit number / name.
$table->string('room')->nullable();
// ── Postal / administrative divisions ───────────────────
// Postal / ZIP code.
$table->string('postal_code')->nullable();
// City, town, village or locality name.
$table->string('city')->nullable();
// State, province, canton, prefecture or equivalent.
$table->string('state')->nullable();
// County, district or other sub-state administrative area.
$table->string('county')->nullable();
// ISO 3166-1 alpha-2 country code (e.g. "AT", "US", "JP").
$table->string('country_code', 2)->nullable();
// ── Coordinates (WGS-84) ────────────────────────────────
// Latitude in decimal degrees (90 to +90).
$table->decimal('latitude', 10, 7)->nullable();
// Longitude in decimal degrees (180 to +180).
$table->decimal('longitude', 10, 7)->nullable();
// Altitude in metres above mean sea level (AMSL). Positive = above, negative = below.
$table->decimal('altitude', 10, 2)->nullable();
// ── Building amenities ───────────────────────────────────
// Whether the building has an elevator (relevant for moving, deliveries).
$table->boolean('has_elevator')->default(false);
// ── Additional properties ───────────────────────────────
// Free-form notes (e.g. delivery instructions, landmark descriptions).
$table->text('notes')->nullable();
// Flexible JSON bucket for any extra data the consuming app needs
// (e.g. Plus Codes, what3words, timezone, formatted display string).
$table->json('meta')->nullable();
$table->timestamps();
$table->softDeletes();
// ── Indexes ─────────────────────────────────────────────
$table->index('country_code');
$table->index('postal_code');
$table->index('city');
$table->index(['latitude', 'longitude']);
});
/*
|----------------------------------------------------------------------
| address_links — polymorphic pivot ("addressable")
|----------------------------------------------------------------------
|
| Links an address to any Eloquent model (User, Company, Order …).
| The same address row can be linked to many models, and a single model
| can have many addresses (each with a different purpose / type).
|
| `type` enum value describing the purpose of this link
| `label` optional free-text override (handy for "Other" type)
| `is_primary` marks ONE link per type per model as the primary
| `active_from` when this link becomes effective
| `active_until` when this link expires / is superseded
| `meta` JSON bucket for developer-defined extra data
|
*/
Schema::create(config('addresses.table_names.address_links', 'address_links'), function (Blueprint $table) {
$table->uuid('id')->primary();
// ── Foreign key to the address ──────────────────────────
$table->foreignUuid('address_id')
->constrained(config('addresses.table_names.addresses', 'addresses'))
->cascadeOnDelete();
// ── Polymorphic owner ───────────────────────────────────
// The model this address is linked to (e.g. App\Models\User, App\Models\Company).
$table->morphs('addressable');
// ── Link semantics ──────────────────────────────────────
// The purpose of this link, drawn from AddressLinkType enum.
$table->string('type')->default('other');
// Optional human-readable label to refine or override the type
// (useful when type = "other" or when several links share the same type).
$table->string('label')->nullable();
// Whether this is the primary address for this type on the model.
$table->boolean('is_primary')->default(false);
// ── Temporal validity ───────────────────────────────────
// When this link becomes active (null = immediately).
$table->timestamp('active_from')->nullable();
// When this link ceases to be active (null = indefinitely).
$table->timestamp('active_until')->nullable();
// ── Extra data ──────────────────────────────────────────
// JSON bucket for any developer-defined data on the pivot
// (e.g. delivery window, access codes, department reference).
$table->json('meta')->nullable();
$table->timestamps();
// ── Indexes ─────────────────────────────────────────────
$table->index(['addressable_type', 'addressable_id', 'type'], 'addr_link_owner_type');
$table->index('type');
$table->index('is_primary');
});
/*
|----------------------------------------------------------------------
| address_assignments — reference an AddressLink from another context
|----------------------------------------------------------------------
|
| While an AddressLink says "this Address belongs to User X as their
| Office", an AddressAssignment says "Job Y uses that specific link
| for its pickup location."
|
| `role` context-specific purpose (e.g. "pickup", "delivery", "origin")
| `label` optional free-text label
| `meta` JSON bucket for developer-defined data
|
*/
Schema::create(config('addresses.table_names.address_assignments', 'address_assignments'), function (Blueprint $table) {
$table->uuid('id')->primary();
// ── Foreign key to the address link ─────────────────────
$table->foreignUuid('address_link_id')
->constrained(config('addresses.table_names.address_links', 'address_links'))
->cascadeOnDelete();
// ── Polymorphic consumer ────────────────────────────────
// The model this address link is assigned to (e.g. Job, Order, Event).
$table->morphs('assignable');
// ── Assignment semantics ────────────────────────────────
// Context-specific role for this assignment (e.g. "pickup", "delivery").
$table->string('role')->nullable();
// Optional human-readable label.
$table->string('label')->nullable();
// ── Contact / access overrides ──────────────────────────
// These let the assignment specify WHO to contact and WHERE
// exactly within the building, independent of the base address.
// The address stays generic ("Main Street 5, 1010 Vienna")
// while the assignment adds context ("3rd floor, door 12, ring Müller").
// Name on the door / bell / intercom.
$table->string('name_on_door')->nullable();
// Contact email for this specific assignment.
$table->string('email')->nullable();
// Contact phone for this specific assignment.
$table->string('phone')->nullable();
// Floor override (when the base address doesn't specify one,
// or this assignment targets a different floor).
$table->string('floor')->nullable();
// Door / apartment / unit number override.
$table->string('door')->nullable();
// ── Extra data ──────────────────────────────────────────
$table->json('meta')->nullable();
$table->timestamps();
// ── Indexes ─────────────────────────────────────────────
$table->index(['assignable_type', 'assignable_id', 'role'], 'addr_assign_owner_role');
$table->index('role');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists(config('addresses.table_names.address_assignments', 'address_assignments'));
Schema::dropIfExists(config('addresses.table_names.address_links', 'address_links'));
Schema::dropIfExists(config('addresses.table_names.addresses', 'addresses'));
}
};