'array', 'created_at' => 'datetime', 'updated_at' => 'datetime', ]; // ================================ // RELAZIONI // ================================ /** * Stabile di appartenenza */ public function stabile() { return $this->belongsTo(Stabile::class, 'stabile_id'); } /** * Elemento padre (palazzina per scale, scala per piani) */ public function parent() { return $this->belongsTo(self::class, 'parent_id'); } /** * Elementi figli (scale per palazzina, piani per scala) */ public function children() { return $this->hasMany(self::class, 'parent_id'); } // ================================ // SCOPE // ================================ /** * Filtra per tipo di struttura */ public function scopeTipo($query, string $tipo) { return $query->where('tipo', $tipo); } /** * Solo elementi di primo livello (palazzine) */ public function scopeRoot($query) { return $query->whereNull('parent_id'); } /** * Solo elementi attivi */ public function scopeAttivi($query) { return $query->where('stato', 'attivo'); } // ================================ // ACCESSORS & MUTATORS // ================================ /** * Badge tipo struttura */ public function getTipoBadgeAttribute(): string { return match($this->tipo) { 'palazzina' => 'bg-primary', 'scala' => 'bg-info', 'piano' => 'bg-success', 'locale' => 'bg-warning', default => 'bg-secondary' }; } /** * Icona tipo struttura */ public function getTipoIconaAttribute(): string { return match($this->tipo) { 'palazzina' => 'fas fa-building', 'scala' => 'fas fa-stairs', 'piano' => 'fas fa-layer-group', 'locale' => 'fas fa-door-open', default => 'fas fa-cube' }; } /** * Path completo gerarchico */ public function getPathCompletoAttribute(): string { $path = [$this->nome]; $parent = $this->parent; while ($parent) { array_unshift($path, $parent->nome); $parent = $parent->parent; } return implode(' > ', $path); } // ================================ // METODI STATICI // ================================ /** * Costruisci albero gerarchico per stabile */ public static function alberoStabile(int $stabileId): array { $strutture = self::where('stabile_id', $stabileId) ->orderBy('tipo') ->orderBy('codice') ->get(); return self::buildTree($strutture); } /** * Costruisce struttura ad albero */ private static function buildTree($elements, $parentId = null): array { $branch = []; foreach ($elements as $element) { if ($element->parent_id == $parentId) { $children = self::buildTree($elements, $element->id); if ($children) { $element->children = $children; } $branch[] = $element; } } return $branch; } // ================================ // COSTANTI // ================================ const TIPI_STRUTTURA = [ 'palazzina' => 'Palazzina', 'scala' => 'Scala', 'piano' => 'Piano', 'locale' => 'Locale Tecnico', ]; const STATI = [ 'attivo' => 'Attivo', 'inattivo' => 'Inattivo', 'manutenzione' => 'In Manutenzione', ]; }