From 903cd3bb08ad9cfc20bfd4ab26a29aea158a0fa5 Mon Sep 17 00:00:00 2001 From: "Fabian @ Blax Software" Date: Fri, 17 Apr 2026 07:07:11 +0200 Subject: [PATCH] feat: add has_elevator to Address, contact/access fields to AddressAssignment - Address: has_elevator (bool) column for building elevator status - AddressAssignment: name_on_door, email, phone, floor, door columns for context-specific contact and access info - AddressAssignment: effective_floor/effective_door accessors (assignment overrides base address) --- .../create_blax_address_tables.php.stub | 26 +++++++++++++++ src/Models/Address.php | 7 ++-- src/Models/AddressAssignment.php | 32 +++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/database/migrations/create_blax_address_tables.php.stub b/database/migrations/create_blax_address_tables.php.stub index 70c4f94..506ea19 100644 --- a/database/migrations/create_blax_address_tables.php.stub +++ b/database/migrations/create_blax_address_tables.php.stub @@ -76,6 +76,10 @@ return new class extends Migration // 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(); @@ -187,6 +191,28 @@ return new class extends Migration // 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(); diff --git a/src/Models/Address.php b/src/Models/Address.php index 74f21cc..32e2e64 100644 --- a/src/Models/Address.php +++ b/src/Models/Address.php @@ -28,6 +28,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property float|null $latitude – Decimal degrees (−90 … +90) * @property float|null $longitude – Decimal degrees (−180 … +180) * @property float|null $altitude – Metres AMSL (positive = above, negative = below) + * @property bool $has_elevator – Whether the building has an elevator * @property string|null $notes – Free-form notes / delivery instructions * @property object|null $meta – Arbitrary JSON data * @property \Carbon\Carbon $created_at @@ -60,6 +61,7 @@ class Address extends Model 'latitude', 'longitude', 'altitude', + 'has_elevator', 'notes', 'meta', ]; @@ -70,8 +72,9 @@ class Address extends Model protected $casts = [ 'latitude' => 'float', 'longitude' => 'float', - 'altitude' => 'float', - 'meta' => 'object', + 'altitude' => 'float', + 'has_elevator' => 'boolean', + 'meta' => 'object', ]; /* diff --git a/src/Models/AddressAssignment.php b/src/Models/AddressAssignment.php index 425e9ac..9f1c005 100644 --- a/src/Models/AddressAssignment.php +++ b/src/Models/AddressAssignment.php @@ -25,6 +25,11 @@ use Illuminate\Database\Eloquent\Model; * @property int $assignable_id – Morph ID of the consuming model * @property string|null $role – Context-specific purpose ("pickup", "delivery", …) * @property string|null $label – Free-text label + * @property string|null $name_on_door – Name on door / bell / intercom + * @property string|null $email – Contact email for this assignment + * @property string|null $phone – Contact phone for this assignment + * @property string|null $floor – Floor override for this assignment + * @property string|null $door – Door / apartment / unit override * @property object|null $meta – Arbitrary JSON data * @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $updated_at @@ -42,6 +47,11 @@ class AddressAssignment extends Model 'assignable_id', 'role', 'label', + 'name_on_door', + 'email', + 'phone', + 'floor', + 'door', 'meta', ]; @@ -114,6 +124,28 @@ class AddressAssignment extends Model return $this->morphTo(); } + /* + |-------------------------------------------------------------------------- + | Accessors — effective values (assignment overrides base address) + |-------------------------------------------------------------------------- + */ + + /** + * The effective floor: assignment's floor if set, otherwise the base address's floor. + */ + public function getEffectiveFloorAttribute(): ?string + { + return $this->floor ?? $this->addressLink?->address?->floor; + } + + /** + * The effective door/room: assignment's door if set, otherwise the base address's room. + */ + public function getEffectiveDoorAttribute(): ?string + { + return $this->door ?? $this->addressLink?->address?->room; + } + /* |-------------------------------------------------------------------------- | Scopes